Magento 2: làm thế nào để các bộ phận / phần của khách hàng hoạt động?


49

Gần đây tôi đã bắt gặp một khái niệm mới trong Magento 2 mà tôi thấy thú vị: phần khách hàng

Một số bạn có thể nhận thấy sự hiện diện của sections.xmlcác tệp trông như thế này:

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

Từ những gì tôi hiểu, các tệp đó chỉ định phần khách hàng nào sẽ được cập nhật khi hành động tương ứng được gọi.

Tôi nhận thấy ví dụ với Magento/Checkout/etc/frontend/sections.xmlphần sau:

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

Là những gì kích hoạt cập nhật minicart sau khi bạn đã thêm một sản phẩm vào giỏ hàng.

Tôi đã thử tạo một mô-đun tùy chỉnh với etc/frontend/sections.xmltệp sau để kiểm tra tính năng đó:

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

Nhưng dường như nó không cố cập nhật phần giỏ hàng của tôi khi tôi đến trang giỏ hàng (không có yêu cầu GET trong bảng điều khiển). Có vẻ như toàn bộ chức năng phần này được xử lý bởi Magento_Customermô-đun theo một cách nào đó.

  • Chính xác những phần đó là gì? Làm thế nào để bạn xác định một phần?
  • Làm thế nào là các cập nhật phần được kích hoạt?
  • (Tùy chọn) Làm cách nào tôi có thể sửa mã kiểm tra của mình để cập nhật minicart khi tôi đến trang giỏ hàng?

Điều này có được kích hoạt trong bộ điều khiển và hành động được tham chiếu như phương thức thực thi hoặc một số cách khác không?
LM_Fielding

1
@LM_Fielding thấy tôi vừa đăng một câu trả lời: magento.stackexchange.com/a/142350/2380
Raphael tại Digital Pianism

Câu trả lời:


82

Chính xác những phần đó là gì?

Một phần là một phần dữ liệu khách hàng được nhóm lại với nhau. Mỗi phần được đại diện bởi khóa được sử dụng để truy cập và quản lý dữ liệu và chính dữ liệu. Magento tải các phần theo yêu cầu AJAX /customer/section/load/và lưu trữ dữ liệu được tải trong bộ nhớ cục bộ của trình duyệt theo khóa mage-cache-storage. Magento theo dõi khi một số phần được thay đổi và tải phần cập nhật tự động.

Làm thế nào để bạn xác định một phần?

Một phần được xác định trong di.xmltệp bằng cách thêm một phần mới vào nhóm phần

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

Vì vậy, ở đây hai phần mới được đăng ký cartdirectory-data. Magento\Checkout\CustomerData\CartMagento\Checkout\CustomerData\DirectoryDatathực hiện Magento\Customer\CustomerData\SectionSourceInterfacevà cung cấp dữ liệu thực tế như là kết quả của getSectionDataphương pháp.

Làm thế nào là các cập nhật phần được kích hoạt?

Magento giả định rằng dữ liệu cá nhân của khách hàng được thay đổi khi một khách hàng gửi một số yêu cầu sửa đổi trạng thái ( POST, PUT, DELETE). Để giảm thiểu tải trên máy chủ, nhà phát triển nên chỉ định hành động (hoặc yêu cầu) cập nhật phần dữ liệu khách hàng nào etc/section.xml.

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

Tên hành động là một mẫu khóa hành động. Khi người dùng gọi hành động phù hợp với mẫu đã chỉ định, Magento sẽ phát hiện phần tương ứng đó đã lỗi thời và tải lại. Nếu tên hành động *có nghĩa là phần đó sẽ được cập nhật trên mỗi yêu cầu POST và PUT. Nếu thẻ phần bị bỏ lỡ thì tất cả các phần sẽ được cập nhật.

Vì vậy, về mặt khái niệm, điều này là sai khi cập nhật giỏ hàng nhỏ khi bạn trang giàu giỏ hàng. Tại thời điểm này, giỏ hàng nhỏ (hoặc phần giỏ hàng) đã được cập nhật.

Bạn có thể tìm thêm thông tin về Dữ liệu khách hàng tại đây


Thực hiện nội bộ

Để hiểu khi nào và làm thế nào các phần được cập nhật, hãy xem thực hiện. Chìa khóa để hiểu là các tập tin magento2ce/app/code/Magento/Customer/view/frontend/web/js/section-config.jsmagento2ce/app/code/Magento/Customer/view/frontend/web/js/customer-data.js.

Vào cuối của một trong hai trình xử lý sự kiện được đăng ký ajaxCompletesubmit. Điều đó có nghĩa rằng khi dưới mọi hình thức được đăng tải (với POST hoặc các phương pháp PUT) đến máy chủ, hoặc khi JavaScript sẽ gửi một AJAX, POSThoặc PUTyêu cầu, xử lý sẽ được gọi. Cả hai trình xử lý có logic tương tự: với sự trợ giúp của Magento_Customer/js/section-configkiểm tra nên có bất kỳ phần nào được cập nhật hay không. Nếu một số phần nên được cập nhật thì customerData.invalidate(sections)được gọi. Và sau đó tất cả các phần không hợp lệ được tải từ một máy chủ.

Vậy làm thế nào để Magento_Customer/js/section-configbiết phần nào nên được gỡ bỏ và trên hành động nào? Câu trả lời là trong 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>

Theo cách đó, một máy chủ chuyển cấu hình các phần được hợp nhất vào trình duyệt.

Vì vậy, giả sử tất cả điều đó, phần chỉ có thể được cập nhật bằng cách gửi biểu mẫu POST hoặc PUT hoặc yêu cầu AJAX

Ngoài ra, chỉ có hai lưu ý:

  • tất cả được mô tả ở đây là triển khai nội bộ và có thể được thay đổi, do đó bạn chỉ có thể sử dụng một cách an toàn các phần của tệp XML và mong đợi các cập nhật phần khi các hành động POST hoặc PUT hoặc DELETE được chỉ định được kích hoạt.
  • nếu bạn chắc chắn rằng bạn thực sự cần cập nhật một số phần bạn luôn có thể làm một cái gì đó như thế này: require('Magento_Customer/js/customer-data').reload(['cart'], false)

Tuyệt vời cảm ơn vì điều đó. Bất kỳ cách nào bạn có thể cho biết tại sao mã trong câu hỏi của tôi không làm mới giỏ hàng nhỏ khi tôi đến trang giỏ hàng?
Raphael tại Nghệ thuật piano kỹ thuật số

1
@RaphaelatDigitalPianism, tôi đã cập nhật nhận xét của mình bằng câu trả lời
Volodymyr Kublytskyi

Tôi đang thực hiện một cuộc gọi ajax tùy chỉnh trong trang giỏ hàng, tôi không cần cuộc gọi phần tải khách hàng này. Làm thế nào tôi có thể tránh điều này? magento.stackexchange.com/questions/156425/ từ
sawi 17/2/2017

5

Hành động mà bạn đã xác định trong thẻ sẽ được gợi lên thông qua yêu cầu POST. ví dụ:

Ngoài ra, nếu bạn muốn làm mới dữ liệu khách hàng trong tất cả các phần, chỉ cần sử dụng (Xem nhà cung cấp / magento / mô-đun-khách hàng / etc / frontend / part.xml)

Bạn cũng có thể nhìn vào phần cuối của tập tin vendor/magento/module-customer/view/frontend/web/js/section-‌​config.js
Tìm mã:

$ (tài liệu) .on ('gửi', chức năng (sự kiện) { 
    phần var; 
    if (event.target.method.match (/ post | put / i)) { 
        phần = phầnConfig.getAffectedSections (event.target.action);
        if (phần) { 
            customerData.invalidate (phần); 
        } 
    } 
});

Bạn cũng có thể xem phần cuối của nhà cung cấp tệp / magento / mô-đun-khách hàng / xem / frontend / web / js / part-config.js Tìm mã $ (tài liệu) .on ('submit', function (event) {var mục; ;
lemk0

3

Một cách hacky tôi tìm thấy để làm điều đó:

Trong lớp hành động của tôi chuyển hướng đến giỏ hàng tôi làm:

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

Sau đó, tôi đã thêm các mục sau vào trang giỏ hàng của mình:

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

Sau đó, trong khối của tôi, tôi có:

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

Refresh.phplớp hành động của tôi trông như thế này:

<?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, phần của tôi thậm chí không cố cập nhật giỏ hàng khi tôi gửi yêu cầu bài đăng đến url trong tệp ... Bạn có ý tưởng nào không?
LM_Fielding

@LM_Fielding vâng Tôi có cùng một người, hãy đọc câu trả lời của tôi
Raphael tại Digital Pianism

Vì vậy, để làm cho nó hoạt động, chúng ta phải viết này? Là hành vi mặc định bị phá vỡ hoặc tôi hiểu lầm?
LM_Fielding

@LM_Fielding tốt Tôi không biết đó là lý do tại sao tôi hỏi câu hỏi này và tôi không nhận được câu trả lời hay nào về nó. Như tôi đã nói đây là cách "hacky" mà tôi tìm thấy để làm điều đó.
Raphael tại Nghệ thuật piano kỹ thuật số

Nó chắc chắn sử dụng một url tương đối cho tôi - nó không kích hoạt cập nhật phần.
LM_Fielding

0

Tôi đã phải đối mặt với cùng một vấn đề như tác giả của câu hỏi. Sau vài giờ nghiên cứu và tìm hiểu về tài liệu và mã lõi, tôi đột nhiên có giải pháp. Trong trường hợp của tôi, tôi đã nhận được tệp ... / etc / frontend / part.xml với

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

Và nó không muốn làm việc. Sau khi đọc chủ đề này và vấn đề này https://github.com/magento/magento2/issues/3287 tôi đã bối rối đến mức bắt đầu thử nghiệm. Đối với tôi giúp thêm dấu gạch chéo:

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

Hy vọng nó sẽ giúp ai đó dành ít thời gian hơn cho việc tìm kiếm giải pháp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.