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.