Magento 2:顧客セクション/sections.xmlはどのように機能しますか?


49

最近、Magento 2の新しいコンセプトに出くわしました。それは顧客のセクションです。

一部のsections.xmlユーザーは、次のようなファイルの存在に気付いているかもしれません。

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

私が理解したことから、これらのファイルは、対応するアクションが呼び出されたときに更新される顧客セクションを指定します。

たとえばMagento/Checkout/etc/frontend/sections.xml、次の部分に気付きました。

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

商品をカートに追加した後、ミニカートの更新をトリガーするものです。

etc/frontend/sections.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="checkout/cart/index">
        <section name="cart"/>
    </action>
</config>

ただし、カートページにアクセスしたときにカートセクションを更新しようとしていないようです(コンソールにGETリクエストがありません)。このセクション全体の機能はMagento_Customer、何らかの方法でモジュールによって処理されるようです。

  • それらのセクションは何ですか?セクションをどのように定義しますか?
  • セクションの更新はどのようにトリガーされますか?
  • (オプション)カートページにアクセスしたときにテストコードを修正してミニカートを更新するにはどうすればよいですか?

これは、実行メソッドまたは他の方法などによって参照されるコントローラーおよびアクションでトリガーされますか?
LM_Fielding

1
@LM_Fielding答えを投稿したばかりです:magento.stackexchange.com/a/142350/2380
Digital PianismのRaphael

回答:


82

それらのセクションは何ですか?

セクションは、グループ化された顧客データです。各セクションは、データおよびデータ自体へのアクセスと管理に使用されるキーで表されます。Magentoは、AJAXリクエストによってセクションを/customer/section/load/ロードし、ロードされたデータをブラウザのローカルストレージのキーの下にキャッシュしますmage-cache-storage。一部のセクションが変更されると、Magentoは追跡し、更新されたセクションを自動的にロードします。

セクションをどのように定義しますか?

di.xmlセクションプールに新しいセクションを追加することでファイルに定義されたセクション

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

だからここに二つの新しいセクションが登録されているcartdirectory-data。メソッドの結果として実際のデータMagento\Checkout\CustomerData\CartMagento\Checkout\CustomerData\DirectoryData実装Magento\Customer\CustomerData\SectionSourceInterfaceおよび提供しますgetSectionData

セクションの更新はどのようにトリガーされますか?

Magentoのは、顧客がいくつかの状態変更要求を送信するときに、お客様の個人データが変更されていることを前提と(POSTPUTDELETE)。サーバーの負荷を最小限に抑えるために、開発者は、どのアクション(または要求)がのどの顧客データセクションを更新するかを指定する必要がありますetc/section.xml

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

アクション名はアクションキーパターンです。ユーザーが指定されたパターンに一致するアクションを呼び出すと、Magentoは対応するセクションが古いことを検出し、再度ロードします。アクション名が*それである場合は、各POSTおよびPUT要求でセクションが更新されることを意味します。セクションタグが欠落している場合、すべてのセクションが更新されます。

したがって、概念的には、リッチカートページでミニカートを更新するのは間違っています。この時点で、ミニカート(またはカートセクション)は既に更新されているはずです。

顧客データの詳細については、こちらをご覧ください


内部実装

セクションが更新されるタイミングと方法を理解するために、実装を見てみましょう。理解の鍵はファイルmagento2ce/app/code/Magento/Customer/view/frontend/web/js/section-config.jsmagento2ce/app/code/Magento/Customer/view/frontend/web/js/customer-data.js

2つのイベントハンドラーの最後の1つが終了するajaxCompleteと、とに登録されsubmitます。つまり、フォームが(POSTまたはPUTメソッドを使用して)サーバーに投稿されるか、JavaScriptがAJAXPOSTまたはPUTリクエストを送信すると、ハンドラーが呼び出されます。両方のハンドラーには同様のロジックがMagento_Customer/js/section-configあります。チェックの助けを借りて、セクションを更新するかどうかを指定する必要があります。一部のセクションを更新する必要がある場合customerData.invalidate(sections)は、が呼び出されます。その後、無効化されたすべてのセクションがサーバーからロードされます。

では、どのMagento_Customer/js/section-configセクションを削除する必要があり、どのアクションを実行するのかをどうやって知るのでしょうか?答えは次のとおりです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>

このようにして、サーバーはマージされたセクションの構成をブラウザーに渡します。

そのため、セクションはPOSTまたはPUTフォームの送信またはAJAXリクエストによってのみ更新される可能性があります

さらに、2つのメモのみがあります。

  • ここで説明されているものはすべて内部実装であり、変更される可能性があるため、sections.xmlのみを安全に使用し、指定されたPOSTまたはPUTまたはDELETEアクションがトリガーされたときにセクションの更新を期待できます。
  • 確かに、いくつかのセクションを本当に更新する必要がある場合は、いつでも次のようなことができます。 require('Magento_Customer/js/customer-data').reload(['cart'], false)

本当にありがとう。私の質問のコードがカートページに到達したときにミニカートを更新しない理由を知ることができますか?
デジタルピアニズムのラファエル

1
@RaphaelatDigitalPianism、私は答えと私のコメント更新しました
ボロディミールKublytskyi

カートページでカスタムAjax呼び出しを行っています。この顧客読み込みセクション呼び出しは必要ありません。どうすればこれを回避できますか?magento.stackexchange.com/questions/156425/...
seeni

5

タグで定義したアクションは、POSTリクエストで呼び出す必要があります。例えば:

また、すべてのセクションで顧客データを更新する場合は、(vendor / magento / module-customer / etc / frontend / sections.xmlをご覧ください)

また、ファイルの終わりを見vendor/magento/module-customer/view/frontend/web/js/section-‌​config.js
てコードを見つけることもできます。

$(document).on( 'submit'、function(event){ 
    varセクション; 
    if(event.target.method.match(/ post | put / i)){ 
        セクション= sectionConfig.getAffectedSections(event.target.action);
        if(セクション){ 
            customerData.invalidate(sections); 
        } 
    } 
});

ファイルの最後を見ることもできますvendor / magento / module-customer / view / frontend / web / js / section-config.jsコードを見つける$(document).on( 'submit'、function(event){varセクション; if(event.target.method.match(/ post | put / i)){セクション= sectionConfig.getAffectedSections(event.target.action); if(セクション){customerData.invalidate(sections);}}}) ;
lemk0

3

私がそれをすることがわかったハックな方法:

カートにリダイレクトするアクションクラスでは、次のことを行います。

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

次に、カートページに次を追加しました。

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

それから私のブロックで私は持っています:

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.phpアクションクラスは次のようになります。

<?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、sections.xmlは、ファイル内のURLに投稿リクエストを送信してもカートを更新しようとしません。
LM_Fielding

@LM_Fieldingはい私には同じ人がいました、私の答えを読んでください
Digital PianismのRaphael

動作させるには、これを書く必要がありますか?デフォルトの動作は壊れていますか、または誤解していますか?
LM_Fielding

@LM_Fieldingよくわからないので、この質問をしたのですが、それについて良い答えが得られませんでした。私が言ったように、これは私がそれをするのを見つけた「ハックな」方法です。
デジタルピアニズムのラファエル

それは間違いなく私にとって相対的なURLを使用していました-セクションの更新をトリガーしません。
LM_Fielding

0

私は質問の著者と同じ問題に直面しています。ドキュメントとコアコードの調査とダギングの数時間後、私は突然解決策を得ました。私の場合、... /etc/frontend/sections.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>

そして、それは働きたくありませんでした。このトピックとこの問題https://github.com/magento/magento2/issues/3287を読んだ後、 私はとても混乱して実験を始めました。私はスラッシュを追加するのに役立ちます:

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

誰かが解決策を見つけるために費やす時間を減らすのに役立つことを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.