Magento 2: come funzionano le sezioni / sezioni.xml dei clienti?


49

Di recente mi sono imbattuto in un nuovo concetto di Magento 2 che ho trovato interessante: sezioni clienti

Alcuni di voi potrebbero aver notato la presenza di sections.xmlfile che assomigliano a questo:

<?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>

Da quello che ho capito, quei file specificano quali sezioni del cliente devono essere aggiornate quando viene chiamata l'azione corrispondente.

Ho notato ad esempio con la Magento/Checkout/etc/frontend/sections.xmlparte seguente:

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

È ciò che attiva l'aggiornamento della minicart dopo aver aggiunto un prodotto al carrello.

Ho provato a creare un modulo personalizzato con il seguente etc/frontend/sections.xmlfile per testare quella funzione:

<?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>

Ma non sembra provare ad aggiornare la sezione del mio carrello quando raggiungo la pagina del carrello (nessuna richiesta GET nella console). Sembra che questa intera sezione sia gestita dal Magento_Customermodulo in qualche modo.

  • Cosa sono esattamente quelle sezioni? Come si definisce una sezione?
  • Come vengono attivati ​​gli aggiornamenti della sezione?
  • (Facoltativo) Come posso correggere il mio codice di prova per aggiornare la minicart quando raggiungo la pagina del carrello?

Questo è attivato nel controller e l'azione a cui fa riferimento come ad esempio un metodo di esecuzione o in qualche altro modo?
— LM_Fielding

1
@LM_Fielding vedi che ho appena pubblicato una risposta: magento.stackexchange.com/a/142350/2380
— Raffaello al Pianismo digitale

Risposte:


82

Cosa sono esattamente quelle sezioni?

Una sezione è un pezzo di dati dei clienti raggruppati insieme. Ogni sezione è rappresentata dalla chiave utilizzata per accedere e gestire i dati e i dati stessi. Magento carica sezioni su richiesta AJAX /customer/section/load/e memorizza nella cache i dati caricati nella memoria locale del browser sotto la chiave mage-cache-storage. Magento tiene traccia di quando una sezione viene modificata e carica automaticamente la sezione aggiornata.

Come si definisce una sezione?

Una sezione definita nel di.xmlfile aggiungendo una nuova sezione nel pool di sezioni

<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>

Quindi qui sono registrate due nuove sezioni carte directory-data. Magento\Checkout\CustomerData\Carte Magento\Checkout\CustomerData\DirectoryDataimplementa Magento\Customer\CustomerData\SectionSourceInterfacee fornisce dati effettivi come risultato del getSectionDatametodo.

Come vengono attivati ​​gli aggiornamenti della sezione?

Magento presuppone che i dati privati del cliente è cambiata quando un cliente invia alcune richieste di modifica dello stato ( POST, PUT, DELETE). Per ridurre al minimo il carico sul server, gli sviluppatori dovrebbero specificare quale azione (o richiesta) aggiorna la sezione dei dati del cliente in etc/section.xml.

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

Il nome dell'azione è un modello chiave di azione. Quando un utente chiama all'azione che corrisponde al modello specificato Magento rileverà che la sezione corrispondente è obsoleta e la carica di nuovo. Se il nome dell'azione *indica che la sezione verrà aggiornata su ogni richiesta POST e PUT. Se manca un tag di sezione, tutte le sezioni verranno aggiornate.

Quindi concettualmente questo è sbagliato per aggiornare il mini carrello quando la pagina del carrello è ricca. A questo punto, il mini carrello (o la sezione carrello) dovrebbe già essere aggiornato.

Puoi trovare ulteriori informazioni sui dati dei clienti qui


Implementazione interna

Per capire quando e come vengono aggiornate le sezioni, vediamo l'implementazione. La chiave per comprendere sono i file magento2ce/app/code/Magento/Customer/view/frontend/web/js/section-config.jse magento2ce/app/code/Magento/Customer/view/frontend/web/js/customer-data.js.

Alla fine dell'ultimo uno dei due gestori di eventi sono registrati per ajaxCompletee submit. Ciò significa che quando qualsiasi forma è pubblicato (con POST o metodi PUT) al server, o quando JavaScript invia una AJAX, POSTo PUTrichiesta, verranno richiamati i gestori. Entrambi i gestori hanno una logica simile: con l'aiuto di Magento_Customer/js/section-configcheck dovrebbe essere aggiornata o meno qualsiasi sezione. Se alcune sezioni devono essere aggiornate, customerData.invalidate(sections)viene chiamato. E in seguito tutte le sezioni invalidate vengono caricate da un server.

Quindi, come fa a Magento_Customer/js/section-configsapere quale sezione dovrebbe essere rimossa e su quale azione? La risposta è in 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>

In tal modo, un server passa la configurazione delle sezioni unite a un browser.

Quindi, supponendo tutto ciò, la sezione può essere aggiornata solo tramite l'invio di un modulo POST o PUT o una richiesta AJAX

Inoltre, ci sono solo due note:

  • tutto ciò che è descritto qui è un'implementazione interna e può essere modificato, quindi puoi tranquillamente utilizzare solo sezioni.xml e aspettarti aggiornamenti di sezione quando vengono attivate le azioni POST o PUT o DELETE specificate.
  • se sei sicuro di aver davvero bisogno di aggiornare alcune sezioni puoi sempre fare qualcosa del genere: require('Magento_Customer/js/customer-data').reload(['cart'], false)

Fantastico grazie per quello. In qualche modo puoi dire perché il codice nella mia domanda non aggiorna il mini carrello quando raggiungo la pagina del carrello?
— Raffaello al Pianismo digitale,

1
@RaphaelatDigitalPianism, ho aggiornato il mio commento con la risposta
— Volodymyr Kublytskyi

Sto effettuando una chiamata Ajax personalizzata nella pagina del carrello, non ho bisogno di questa chiamata alla sezione di caricamento del cliente. Come posso evitarlo? magento.stackexchange.com/questions/156425/…
— seeni

5

L'azione definita nel tag deve essere evocata tramite la richiesta POST. per esempio:

Inoltre, se desideri aggiornare i dati dei clienti in tutte le sezioni, utilizza semplicemente (Guarda fornitore / magento / modulo-cliente / etc / frontend / sezioni.xml)

Puoi anche guardare la fine del file vendor/magento/module-customer/view/frontend/web/js/section-‌​config.js
Trova il codice:

$ (documento) .on ('submit', funzione (evento) { 
    sezioni var; 
    if (event.target.method.match (/ post | put / i)) { 
        sezioni = sectionConfig.getAffectedSections (event.target.action);
        if (sezioni) { 
            customerData.invalidate (sezioni); 
        } 
    } 
});

Puoi anche guardare la fine del fornitore di file / magento / module-customer / view / frontend / web / js / section-config.js Trova il codice $ (document) .on ('submit', function (event) {var sezioni; if (event.target.method.match (/ post | put / i)) {sezioni = sectionConfig.getAffectedSections (event.target.action); if (sezioni) {customerData.invalidate (sezioni);}}}) ;
— lemk0

3

Un modo bizzarro che ho trovato per farlo:

Nella mia classe di azioni che reindirizza al carrello faccio:

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

Quindi ho aggiunto quanto segue alla mia pagina del carrello:

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

Quindi nel mio blocco ho:

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 la mia Refresh.phpclasse d'azione si presenta così:

<?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])
        );
    }
}

Raffaele, il mio sezioni.xml non sta nemmeno tentando di aggiornare il carrello quando invio una richiesta di posta all'URL nel file ... Qualche idea?
— LM_Fielding

@LM_Fielding sì Avevo le stesse persone, leggi la mia risposta
— Raffaello al Pianismo digitale

Quindi, per farlo funzionare, dobbiamo scrivere questo? Il comportamento predefinito è rotto o sono incomprensioni?
— LM_Fielding

@LM_Fielding bene Non so che sia per questo che ho posto questa domanda e non ho avuto una buona risposta a riguardo. Come ho detto, questo è il modo "confuso" che ho scoperto di farlo.
— Raffaello al Pianismo digitale,

Stava sicuramente usando un URL relativo per me - non attiva l'aggiornamento della sezione.
— LM_Fielding

0

Ho riscontrato lo stesso problema dell'autore della domanda. Dopo alcune ore di ricerche e analisi nella documentazione e nel codice di base, improvvisamente ho ottenuto la soluzione. Nel mio caso ho ottenuto il file ... / etc / frontend / sezioni.xml con

<?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 non voleva funzionare. Dopo aver letto questo argomento e questo numero https://github.com/magento/magento2/issues/3287, ero così confuso che ho iniziato a sperimentare. Per me aiuta ad aggiungere barre:

 <?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>

Spero che possa aiutare qualcuno a dedicare meno tempo alla ricerca di una soluzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.