Magento 2: bagaimana cara kerja bagian / bagian.xml pelanggan?

49

Baru-baru ini saya menemukan konsep baru di Magento 2 yang menurut saya menarik: bagian pelanggan

Beberapa dari Anda mungkin telah memperhatikan keberadaan sections.xmlfile yang terlihat seperti ini:

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

Dari apa yang saya mengerti, file-file tersebut menentukan bagian pelanggan mana yang harus diperbarui ketika tindakan yang sesuai dipanggil.

Saya perhatikan misalnya dengan Magento/Checkout/etc/frontend/sections.xmlbagian berikut:

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

Apa yang memicu pembaruan minicart setelah Anda menambahkan produk ke troli.

Saya mencoba membuat modul khusus dengan etc/frontend/sections.xmlfile berikut untuk menguji fitur itu:

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

Tetapi sepertinya tidak mencoba memperbarui bagian keranjang saya ketika saya mencapai halaman keranjang (tidak ada permintaan GET di konsol). Sepertinya fungsionalitas seluruh bagian ini ditangani oleh Magento_Customermodul dalam beberapa cara.

  • Apa sebenarnya bagian-bagian itu? Bagaimana Anda mendefinisikan bagian?
  • Bagaimana pembaruan bagian dipicu?
  • (Opsional) Bagaimana cara memperbaiki kode pengujian saya untuk memperbarui minicart ketika saya mencapai halaman keranjang?
Raphael di Digital Pianism
sumber
Apakah ini dipicu pada controller dan action yang dirujuk seperti dengan metode eksekusi atau cara lain?
LM_Fielding
1
@LM_Fielding lihat saya baru saja mengirim jawaban: magento.stackexchange.com/a/142350/2380
Raphael di Digital Pianism

Jawaban:

82

Apa sebenarnya bagian-bagian itu?

Bagian adalah sepotong data pelanggan yang dikelompokkan bersama. Setiap bagian diwakili oleh kunci yang digunakan untuk mengakses dan mengelola data dan data itu sendiri. Magento memuat bagian dengan permintaan AJAX ke /customer/section/load/dan cache data yang dimuat di penyimpanan lokal browser di bawah kunci mage-cache-storage. Magento melacak ketika beberapa bagian diubah dan memuat bagian yang diperbarui secara otomatis.

Bagaimana Anda mendefinisikan bagian?

Bagian yang didefinisikan dalam di.xmlfile dengan menambahkan bagian baru ke bagian kumpulan

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

Jadi di sini dua bagian baru terdaftar cartdan directory-data. Magento\Checkout\CustomerData\Cartdan Magento\Checkout\CustomerData\DirectoryDatamengimplementasikan Magento\Customer\CustomerData\SectionSourceInterfacedan menyediakan data aktual sebagai hasil dari getSectionDatametode.

Bagaimana pembaruan bagian dipicu?

Magento mengasumsikan bahwa data pribadi pelanggan berubah ketika seorang pelanggan mengirimkan beberapa permintaan modifikasi negara ( POST, PUT, DELETE). Untuk meminimalkan beban di server, pengembang harus menentukan tindakan (atau permintaan) mana yang memperbarui bagian data pelanggan etc/section.xml.

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

Nama tindakan adalah pola kunci aksi. Ketika seorang pengguna menelepon untuk bertindak yang cocok dengan pola yang ditentukan Magento akan mendeteksi bahwa bagian yang sesuai sudah usang dan memuatnya lagi. Jika nama tindakan *itu berarti bagian itu akan diperbarui pada setiap permintaan POST dan PUT. Jika tag bagian dilewatkan maka semua bagian akan diperbarui.

Jadi secara konsep ini salah untuk memperbarui mini cart saat Anda kaya halaman cart. Pada titik ini, kereta mini (atau bagian kereta) sudah harus diperbarui.

Anda dapat menemukan informasi lebih lanjut tentang Data Pelanggan di sini


Implementasi Internal

Untuk memahami kapan dan bagaimana bagian diperbarui mari kita lihat implementasi. Kunci untuk memahami adalah file magento2ce/app/code/Magento/Customer/view/frontend/web/js/section-config.jsdan magento2ce/app/code/Magento/Customer/view/frontend/web/js/customer-data.js.

Pada akhir dari salah satu dari dua acara yang didaftarkan oleh penangan ajaxCompletedan submit. Itu berarti bahwa ketika formulir apa pun diposting (dengan metode POST atau PUT) ke server, atau ketika JavaScript mengirim AJAX, POSTatau PUTmeminta, penangan akan dipanggil. Kedua penangan memiliki logika yang sama: dengan bantuan Magento_Customer/js/section-configpemeriksaan harus ada bagian yang diperbarui atau tidak. Jika beberapa bagian harus diperbarui maka customerData.invalidate(sections)dipanggil. Dan kemudian semua bagian yang tidak valid dimuat dari server.

Jadi, bagaimana cara Magento_Customer/js/section-configmengetahui bagian mana yang harus dihapus dan tindakan apa? Jawabannya ada di 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>

Sedemikian rupa, server meneruskan konfigurasi bagian yang digabungkan ke browser.

Jadi dengan asumsi semua itu, bagian dapat diperbarui hanya dengan mengirimkan formulir POST atau PUT atau permintaan AJAX

Selain itu, hanya ada dua catatan:

  • semua yang dijelaskan di sini adalah implementasi internal dan dapat diubah, sehingga Anda hanya dapat menggunakan bagian.xml dengan aman dan mengharapkan pembaruan bagian ketika tindakan POST atau PUT atau DELETE yang ditentukan dipicu.
  • jika Anda yakin, bahwa Anda benar-benar perlu memperbarui beberapa bagian, Anda selalu dapat melakukan sesuatu seperti ini: require('Magento_Customer/js/customer-data').reload(['cart'], false)
Volodymyr Kublytskyi
sumber
Terima kasih luar biasa untuk itu. Bagaimana Anda bisa tahu mengapa kode dalam pertanyaan saya tidak menyegarkan mini cart ketika saya sampai di halaman cart?
Raphael di Digital Pianism
1
@RaphaelatDigitalPianism, saya telah memperbarui komentar saya dengan jawaban
Volodymyr Kublytskyi
Saya membuat panggilan ajax khusus di halaman keranjang, saya tidak perlu panggilan bagian pelanggan ini. Bagaimana saya bisa menghindari ini? magento.stackexchange.com/questions/156425/…
seeni
5

Tindakan yang Anda tetapkan dalam tag harus ditimbulkan melalui permintaan POST. misalnya:

Juga jika Anda ingin me-refresh data pelanggan di semua bagian, gunakan saja (Lihat vendor / magento / module-customer / etc / frontend / parts.xml)

Anda juga dapat melihat di akhir file vendor/magento/module-customer/view/frontend/web/js/section-‌​config.js
Temukan kode:

$ (dokumen) .on ('kirim', fungsi (acara) { 
    bagian var; 
    if (event.target.method.match (/ post | put / i)) { 
        bagian = sectionConfig.getAffectedSections (event.target.action);
        if (bagian) { 
            customerData.invalidate (bagian); 
        } 
    } 
});
lemk0
sumber
Anda juga dapat melihat di akhir vendor file / magento / module-customer / view / frontend / web / js / section-config.js Temukan kode $ (dokumen) .on ('kirim', fungsi (acara) {var bagian; if (event.target.method.match (/ post | put / i)) {bagian = sectionConfig.getAffectedSections (event.target.action); if (bagian) {customerData.invalidate (bagian);}}}) ;
lemk0
3

Saya menemukan cara untuk melakukannya:

Di kelas tindakan saya yang mengarahkan ke keranjang saya lakukan:

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

Kemudian saya menambahkan yang berikut ke halaman kereta saya:

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

Kemudian di blok saya, saya memiliki:

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');
}

Dan Refresh.phpkelas tindakan saya terlihat seperti ini:

<?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 di Digital Pianism
sumber
Raphael, bagian.xml saya bahkan tidak berusaha memperbarui keranjang ketika saya mengirim permintaan posting ke url di file ... Ada ide?
LM_Fielding
@LM_Menemukan ya saya memiliki orang yang sama, baca jawaban saya
Raphael di Digital Pianism
Jadi untuk membuatnya bekerja, kita harus menulis ini? Apakah perilaku default rusak atau saya salah paham?
LM_Fielding
@LM_Menarik dengan baik Saya tidak tahu itu sebabnya saya menanyakan pertanyaan ini dan saya tidak mendapatkan jawaban yang bagus tentang itu. Seperti yang saya katakan ini adalah cara "retas" yang saya temukan untuk melakukannya.
Raphael di Digital Pianism
Itu pasti menggunakan url relatif untuk saya - itu tidak memicu pembaruan bagian.
LM_Fielding
0

Saya menghadapi masalah yang sama dengan penulis pertanyaan. Setelah beberapa jam meneliti dan berkutat dalam dokumentasi dan kode inti, saya tiba-tiba mendapat solusi. Dalam kasus saya, saya dapat file ... / etc / frontend / seksi.xml

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

Dan itu tidak mau bekerja. Setelah membaca topik ini dan masalah ini https://github.com/magento/magento2/issues/3287 saya sangat bingung sehingga mulai bereksperimen. Bagi saya membantu menambahkan garis miring:

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

Semoga ini akan membantu seseorang untuk menghabiskan lebih sedikit waktu untuk menemukan solusi.

Alex Kozyr
sumber