Magento 2: como funcionam as seções / secções.xml do cliente?

49

Recentemente, vim através de um novo conceito no Magento 2 que achei interessante: seções de clientes

Alguns de vocês podem ter notado a presença de sections.xmlarquivos parecidos com este:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
    <action name="sales/guest/reorder">
        <section name="cart"/>
    </action>
    <action name="sales/order/reorder">
        <section name="cart"/>
    </action>
</config>

Pelo que entendi, esses arquivos especificam quais seções do cliente devem ser atualizadas quando a ação correspondente é chamada.

Notei, por exemplo, com Magento/Checkout/etc/frontend/sections.xmla seguinte parte:

<action name="checkout/cart/add">
    <section name="cart"/>
</action>

É o que aciona a atualização do minicart depois de adicionar um produto ao carrinho.

Tentei criar um módulo personalizado com o seguinte etc/frontend/sections.xmlarquivo para testar esse recurso:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
    <action name="checkout/cart/index">
        <section name="cart"/>
    </action>
</config>

Mas parece não tentar atualizar a seção do meu carrinho quando chego à página do carrinho (nenhuma solicitação GET no console). Parece que toda a funcionalidade desta seção é tratada pelo Magento_Customermódulo de alguma forma.

  • O que são exatamente essas seções? Como você define uma seção?
  • Como as atualizações de seção são acionadas?
  • (Opcional) Como posso corrigir meu código de teste para atualizar o minicart quando chego à página do carrinho?
Raphael na Digital Pianism
fonte
Isso é acionado no controlador e ação referenciada como por um método execute ou de alguma outra maneira?
LM_Fielding
1
@LM_Fielding veja Acabei de publicar uma resposta: magento.stackexchange.com/a/142350/2380
Raphael no Digital Pianism

Respostas:

82

O que são exatamente essas seções?

Uma seção é uma parte dos dados do cliente agrupados. Cada seção é representada pela chave usada para acessar e gerenciar dados e dados em si. O Magento carrega seções por solicitação AJAX /customer/section/load/e armazena em cache os dados carregados no armazenamento local do navegador sob a chave mage-cache-storage. O Magento rastreia quando alguma seção é alterada e carrega a seção atualizada automaticamente.

Como você define uma seção?

Uma seção definida no di.xmlarquivo adicionando uma nova seção ao conjunto de seções

<type name="Magento\Customer\CustomerData\SectionPoolInterface">
    <arguments>
        <argument name="sectionSourceMap" xsi:type="array">
            <item name="cart" xsi:type="string">Magento\Checkout\CustomerData\Cart</item>
            <item name="directory-data" xsi:type="string">Magento\Checkout\CustomerData\DirectoryData</item>
        </argument>
    </arguments>
</type>

Então, aqui duas novas seções são registradas carte directory-data. Magento\Checkout\CustomerData\Carte Magento\Checkout\CustomerData\DirectoryDataimplementa Magento\Customer\CustomerData\SectionSourceInterfacee fornece dados reais como resultado do getSectionDatamétodo.

Como as atualizações de seção são acionadas?

Magento assume que os dados privados do cliente é alterada quando um cliente envia uma solicitação de modificação do estado ( POST, PUT, DELETE). Para minimizar a carga no servidor, os desenvolvedores devem especificar em qual ação (ou solicitação) serão atualizadas quais seções de dados do cliente etc/section.xml.

<action name="checkout/cart/add">
    <section name="cart"/>
</action>

Nome da ação é um padrão de chave de ação. Quando um usuário chama uma ação que corresponde ao padrão especificado, o Magento detecta que a seção correspondente está desatualizada e a carrega novamente. Se o nome da ação for *isso significa que a seção será atualizada em cada solicitação POST e PUT. Se a tag da seção estiver ausente, toda a seção será atualizada.

Portanto, conceitualmente, é errado atualizar o carrinho de compras quando a página do carrinho é rica. Neste ponto, o minicarrinho (ou seção do carrinho) já deve estar atualizado.

Você pode encontrar mais informações sobre dados do cliente aqui


Implementação Interna

Para entender quando e como as seções são atualizadas, vamos ver a implementação. A chave para entender são os arquivos magento2ce/app/code/Magento/Customer/view/frontend/web/js/section-config.jse magento2ce/app/code/Magento/Customer/view/frontend/web/js/customer-data.js.

No final do último, um dos dois manipuladores de eventos está registrado para ajaxCompletee submit. Isso significa que quando qualquer forma é publicado (com POST ou métodos PUT) para o servidor, ou quando JavaScript envia um AJAX, POSTou PUTpedido, os manipuladores será invocado. Ambos os manipuladores têm uma lógica semelhante: com a ajuda do Magento_Customer/js/section-configcheque, deve haver qualquer seção atualizada ou não. Se alguma seção deve ser atualizada, então customerData.invalidate(sections)é chamado. E depois todas as seções invalidadas são carregadas de um servidor.

Então, como Magento_Customer/js/section-configsaber qual seção deve ser removida e em qual ação? A resposta está em Magento/Customer/view/frontend/templates/js/section-config.phtml:

<script type="text/x-magento-init">
<?php
     /* @noEscape */ echo $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode([
    '*' => ['Magento_Customer/js/section-config' => [
        'sections' => $block->getSections(),
        'clientSideSections' => $block->getClientSideSections(),
        'baseUrls' => array_unique([
            $block->getUrl(null, ['_secure' => true]),
            $block->getUrl(null, ['_secure' => false]),
        ]),
    ]],
]);
?>
</script>

Dessa forma, um servidor passa a configuração de seções mescladas para um navegador.

Portanto, assumindo tudo isso, a seção pode ser atualizada apenas pelo envio de formulários POST ou PUT ou solicitação AJAX

Além disso, existem apenas duas notas:

  • tudo descrito aqui é de implementação interna e pode ser alterado; portanto, você pode usar com segurança apenas o seções.xml e esperar atualizações de seção quando ações POST, PUT ou DELETE especificadas forem acionadas.
  • se você tem certeza de que realmente precisa atualizar uma seção, sempre pode fazer algo assim: require('Magento_Customer/js/customer-data').reload(['cart'], false)
Volodymyr Kublytskyi
fonte
Agradecimentos impressionantes por isso. De qualquer maneira, você pode dizer por que o código da minha pergunta não atualiza o minicarrinho quando chego à página do carrinho?
Raphael no Digital Pianism
1
@RaphaelatDigitalPianism, eu atualizei meu comentário com a resposta
Volodymyr Kublytskyi
Estou fazendo uma chamada ajax personalizada na página do carrinho, não preciso dessa chamada da seção de carregamento do cliente. Como posso evitar isso? magento.stackexchange.com/questions/156425/...
seeni
5

A ação que você definiu na tag deve ser evocada por meio da solicitação POST. por exemplo:

Além disso, se você deseja atualizar os dados do cliente em todas as seções, use (consulte vendor / magento / module-customer / etc / frontend / seções.xml)

Você também pode ver o final do arquivo. vendor/magento/module-customer/view/frontend/web/js/section-‌​config.js
Encontre o código:

$ (document) .on ('submit', function (event) { 
    seções var; 
    if (event.target.method.match (/ post | put / i)) { 
        seções = sectionConfig.getAffectedSections (event.target.action);
        if (seções) { 
            customerData.invalidate (seções); 
        } 
    } 
});
lemk0
fonte
Você também pode consultar o final do fornecedor de arquivos / magento / module-customer / view / frontend / web / js / section-config.js Encontre o código $ (document) .on ('submit', function (event) {var seções; if (event.target.method.match (/ post | put / i)) {seções = sectionConfig.getAffectedSections (event.target.action); if (seções) {customerData.invalidate (seções);}}}) ;
precisa saber é o seguinte
3

Uma maneira hacky que encontrei para fazer isso:

Na minha classe de ação que redireciona para o carrinho, eu faço:

$this->_checkoutSession->setMinicartNeedsRefresh(true);

Em seguida, adicionei o seguinte à página do meu carrinho:

<?php if ($this->isRefreshRequired()): ?>
    <script type="text/javascript">
        require( [ 'jquery' ], function ($)
        {
            $.ajax({
                url: '<?php echo $this->getRefreshUrl(); ?>',
                type: 'POST'
            });
        });
    </script>
<?php endif; ?>

Então no meu bloco eu tenho:

public function isRefreshRequired()
{
    if ($this->_checkoutSession->getMinicartNeedsRefresh()) {
        $this->_checkoutSession->setMinicartNeedsRefresh(false);
        return true;
    } else {
        return false;
    }
}

/**
 * Get the refresh URL
 * @return string
 */
public function getRefreshUrl()
{
    return $this->getUrl('module/cart/refresh');
}

E minha Refresh.phpclasse de ação é assim:

<?php

namespace Vendor\Module\Controller\Cart;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;

class Refresh extends Action
{

    /**
     * Dummy action class called via AJAX to trigger the section update
     */
    public function execute()
    {
        return $this->getResponse()->representJson(
            $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode(['success'=>true])
        );
    }
}
Raphael na Digital Pianism
fonte
Rafael, meu section.xml nem está tentando atualizar o carrinho quando envio uma solicitação de postagem para o URL no arquivo ... Alguma idéia?
LM_Fielding
@LM_Fielding sim, eu tinha as mesmas pessoas, leia minha resposta
Raphael em Digital pianismo
Então, para que funcione, temos que escrever isso? O comportamento padrão está quebrado ou estou entendendo mal?
LM_Fielding
@LM_Fielding well Eu não sei por isso que fiz essa pergunta e não recebi nenhuma resposta boa sobre isso. Como eu disse, essa é a maneira "hacky" de encontrar isso.
Raphael no Digital Pianism
Definitivamente, estava usando um URL relativo para mim - não aciona a atualização da seção.
LM_Fielding
0

Eu enfrentei o mesmo problema que o autor da pergunta. Depois de algumas horas pesquisando e analisando a documentação e o código principal, de repente consegui uma solução. No meu caso, eu tenho o arquivo ... / etc / frontend / seções.xml com

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
    <action name="roadsignconf/index/addtocart">
        <section name="cart"/>
    </action>
</config>

E não queria funcionar. Depois de ler este tópico e esta edição https://github.com/magento/magento2/issues/3287, fiquei tão confuso que comecei a experimentar. Para mim, ajuda a adicionar barras:

 <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
        <action name="/roadsignconf/index/addtocart/">
            <section name="cart"/>
        </action>
    </config>

Espero que ajude alguém a gastar menos tempo para encontrar a solução.

Alex Kozyr
fonte