bdc / module-contactpreferences
BDCrops ContactPreferences 模块为 Magento 2 扩展。
This package is auto-updated.
Last update: 2024-09-16 18:56:29 UTC
README
此模块用于所有 BDCrops Magento 2 扩展的客户联系偏好设置。了解客户数据对象背后的机制以及部分加载,让我们通过创建一个小模块来使用它,在客户的“我的账户”区域以及结账时添加联系偏好功能。
构建了一个小模块,使我们能够更深入地了解 Magento 的客户数据和部分机制。我们成功构建了一个组件,它被用于客户的“我的账户”页面以及结账页面。
目标
- 为客户账户添加联系偏好
- 管理 Magento 2 中的 CustomerData 实体
- 在 Magento 2 中使用 Section.xml 文件
- 自定义结账流程
- 学习 Magento 2 认证专业开发者考试主题 "自定义结账流程 13%"
1. 如何安装和升级 ContactPreferences
1.1 复制粘贴
如果您不想通过 composer 安装,可以使用此方法。
- 在此处下载最新版本 [链接]
- 将
master.zip
文件解压到app/code/BDC/ContactPreferences
;如果您尚未存在,应该创建一个路径app/code/BDC/ContactPreferences
。 - 转到 Magento 根目录并运行升级命令行以安装
BDC_ContactPreferences
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy
1.2 通过 composer 安装
我们建议您通过 composer 安装 BDC_ContactPreferences 模块。它易于安装、更新和维护。在 Magento 2 根目录中运行以下命令。
composer config repositories.module-contactpreferences git
https://github.com/bdcrops/module-contactpreferences.git
composer require bdcrops/module-contactpreferences:~1.0.0
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy
1.3 升级
composer update bdcrops/module-contactpreferences
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy
如果您的商店处于产品模式,请运行编译
php bin/magento setup:di:compile
2. BDC_ContactPreferences
- 创建 app/code/BDC/ContactPreferences/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="BDC_ContactPreferences" setup_version="1.0.0">
<sequence>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
- 创建 app/code/BDC/ContactPreferences/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'BDC_ContactPreferences',
__DIR__
);
- 创建 app/code/BDC/ContactPreferences/Setup/InstallData.php
<?php
namespace BDC\ContactPreferences\Setup;
class InstallData implements \Magento\Framework\Setup\InstallDataInterface {
protected $customerSetupFactory;
public function __construct(
\Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory
) {
$this->customerSetupFactory = $customerSetupFactory;
}
public function install(\Magento\Framework\Setup\ModuleDataSetupInterface $setup, \Magento\Framework\Setup\ModuleContextInterface $context)
{
$setup->startSetup();
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerSetup->addAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'contact_preferences', [
'type' => 'varchar',
'label' => 'Contact Preferences',
'input' => 'multiselect',
'source' => \BDC\ContactPreferences\Model\Entity\Attribute\Source\Contact\Preferences::class,
'required' => 0,
'sort_order' => 99,
'position' => 99,
'system' => 0,
'visible' => 1,
'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_GLOBAL,
]
);
$contactPreferencesAttr = $customerSetup
->getEavConfig()->getAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'contact_preferences'
);
$forms = [ 'adminhtml_customer', 'customer_account_edit', ];
$contactPreferencesAttr->setData('used_in_forms', $forms)
->setData('is_used_for_customer_segment', true)
->setData('is_system', 0)
->setData('is_user_defined', 1)
->setData('is_visible', 1)
->setData('sort_order', 99);
$contactPreferencesAttr->save();
$setup->endSetup();
}
}
- 创建 app/code/BDC/ContactPreferences/etc/frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="customer" frontName="customer">
<module name="BDC_ContactPreferences" before="Magento_Customer"/>
</route>
</router>
</config>
- 创建 app/code/BDC/ContactPreferences/Controller/Contact/Preferences.php
<?php
namespace BDC\ContactPreferences\Controller\Contact;
use Magento\Framework\App\Action\Context;
use phpDocumentor\Reflection\Types\Boolean;
class Preferences extends \Magento\Customer\Controller\AbstractAccount {
protected $customerSession;
protected $customerRepository;
protected $logger;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Customer\Model\Session $customerSession,
\Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
\Psr\Log\LoggerInterface $logger
) {
$this->customerSession = $customerSession;
$this->customerRepository = $customerRepository;
$this->logger = $logger;
parent::__construct($context);
}
public function execute() {
if ($this->getRequest()->isPost()) {
$resultJson = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_JSON);
if ($this->getRequest()->getParam('load')) {
// This POST is merely to trigger "contact_preferences" section load
} else {
try {
$preferences = implode(',',
array_keys(
array_filter($this->getRequest()->getParams(), function ($_checked, $_preference) {
return filter_var($_checked, FILTER_VALIDATE_BOOLEAN);
}, ARRAY_FILTER_USE_BOTH)
)
);
$customer = $this->customerRepository->getById($this->customerSession->getCustomerId());
$customer->setCustomAttribute('contact_preferences', $preferences);
$this->customerRepository->save($customer);
$this->messageManager->addSuccessMessage(__('Successfully saved contact preferences.'));
} catch (\Exception $e) {
$this->logger->critical($e);
$this->messageManager->addSuccessMessage(__('Error saving contact preferences.'));
}
}
return $resultJson;
} else {
$resultPage = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE);
$resultPage->getConfig()->getTitle()->set(__('My Contact Preferences'));
return $resultPage;
}
}
}
- 创建 app/code/BDC/ContactPreferences/Model/Entity/Attribute/Source/Contact/Preferences.php
<?php
namespace BDC\ContactPreferences\Model\Entity\Attribute\Source\Contact;
class Preferences extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource {
const VALUE_EMAIL = 'email';
const VALUE_PHONE = 'phone';
const VALUE_POST = 'post';
const VALUE_SMS = 'sms';
const VALUE_TELEGRAM = 'telegram';
public function getAllOptions() {
return [
['label' => __('Email'), 'value' => self::VALUE_EMAIL],
['label' => __('Phone'), 'value' => self::VALUE_PHONE],
['label' => __('Post'), 'value' => self::VALUE_POST],
['label' => __('SMS'), 'value' => self::VALUE_SMS],
['label' => __('Telegram'), 'value' => self::VALUE_TELEGRAM],
];
}
}
- 创建 app/code/BDC/ContactPreferences/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Customer\CustomerData\SectionPoolInterface">
<arguments>
<argument name="sectionSourceMap" xsi:type="array">
<item name="contact_preferences" xsi:type="string">BDC\ContactPreferences\CustomerData\Preferences</item>
</argument>
</arguments>
</type>
</config>
- 创建 app/code/BDC/ContactPreferences/CustomerData/Preferences.php
<?php
namespace BDC\ContactPreferences\CustomerData;
class Preferences extends \Magento\Framework\DataObject implements \Magento\Customer\CustomerData\SectionSourceInterface
{
protected $preferences;
protected $customerSession;
public function __construct(
\BDC\ContactPreferences\Model\Entity\Attribute\Source\Contact\Preferences $preferences,
\Magento\Customer\Model\Session $customerSession,
array $data = [] ) {
$this->preferences = $preferences;
$this->customerSession = $customerSession;
parent::__construct($data);
}
public function getSectionData() {
$existingPreferences = explode(',',
$this->customerSession->getCustomer()->getContactPreferences()
);
$availablePreferences = [];
foreach ($this->preferences->getAllOptions() as $_option) {
$availablePreferences[] = [
'label' => $_option['label'],
'value' => $_option['value'],
'checked' => in_array($_option['value'], $existingPreferences)
];
}
return [
'selectOptions' => $availablePreferences,
'isCustomerLoggedIn' => $this->customerSession->isLoggedIn()
];
}
}
- 创建 app/code/BDC/ContactPreferences/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="customer/contact/preferences">
<section name="contact_preferences"/>
</action>
</config>
- 创建 app/code/BDC/ContactPreferences/view/frontend/layout/checkout_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="afterMethods" xsi:type="array">
<item name="children" xsi:type="array">
<item name="contact-preferences" xsi:type="array">
<item name="component" xsi:type="string">BDC_ContactPreferences/js/view/contact-preferences</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
- 创建 app/code/BDC/ContactPreferences/view/frontend/layout/customer_account.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="customer_account_navigation">
<block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-contact-preferences-link">
<arguments>
<argument name="path" xsi:type="string">customer/contact/preferences</argument>
<argument name="label" xsi:type="string" translate="true">My Contact Preferences</argument>
<argument name="sortOrder" xsi:type="number">230</argument>
</arguments>
</block>
</referenceBlock>
</body>
</page>
- 创建 app/code/BDC/ContactPreferences/view/frontend/layout/customer_contact_preferences.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="customer_account"/>
<body>
<referenceContainer name="content">
<block name="contact_preferences"
template="BDC_ContactPreferences::customer/contact/preferences.phtml" cacheable="false"/>
</referenceContainer>
</body>
</page>
- 创建 app/code/BDC/ContactPreferences/view/frontend/templates/customer/contact/preferences.phtml
<div class="contact-preferences" data-bind="scope:'contact-preferences-scope'">
<!-- ko template: getTemplate() --><!-- /ko -->
</div>
<script type="text/x-magento-init">
{
".contact-preferences": {
"Magento_Ui/js/core/app": {
"components": {
"contact-preferences-scope": {
"component": "contactPreferences"
}
}
}
}
}
</script>
- 创建 app/code/BDC/ContactPreferences/view/frontend/requirejs-config.js
var config = {
map: {
'*': {
contactPreferences: 'BDC_ContactPreferences/js/view/contact-preferences'
}
}
};
- 创建 app/code/BDC/ContactPreferences/view/frontend/web/js/view/contact-preferences.js
define([
'uiComponent',
'jquery',
'mage/url',
'Magento_Customer/js/customer-data',
'Magento_Customer/js/model/customer'
], function (Component, $, url, customerData, customer) {
'use strict';
let contactPreferences = customerData.get('contact_preferences');
return Component.extend({
defaults: {
template: 'BDC_ContactPreferences/contact-preferences'
},
initialize: function () {
this._super();
// Trigger "contact_preferences" section load
$.ajax({
type: 'POST',
url: url.build('customer/contact/preferences'),
data: {'load': true},
showLoader: true
});
},
isCustomerLoggedIn: function () {
return contactPreferences().isCustomerLoggedIn;
},
getSelectOptions: function () {
return contactPreferences().selectOptions;
},
saveContactPreferences: function () {
let preferences = {};
$('.contact_preference').children(':checkbox').each(function () {
preferences[$(this).attr('name')] = $(this).attr('checked') ? true : false;
});
$.ajax({
type: 'POST',
url: url.build('customer/contact/preferences'),
data: preferences,
showLoader: true,
complete: function (response) {
// todo
}
});
return true;
}
});
});
- 创建 app/code/BDC/ContactPreferences/view/frontend/web/template/contact-preferences.html
<div class="contact-preferences-component" data-bind="if: isCustomerLoggedIn()">
<div class="step-title iweb-contact-preferences-title" data-role="title" data-bind="i18n: 'Contact Preferences'"></div>
<div class="contact-preferences" data-role="content">
<div class="contact_preference" repeat="foreach: getSelectOptions(), item: '$option'">
<input type="checkbox"
click="saveContactPreferences"
ko-checked="$option().checked"
attr="name: $option().value"/>
<label text="$option().label" attr="for: $option().value"/>
</div>
</div>
</div>
常见问题解答
那些部分究竟是什么?
部分是一组客户数据的集合。每个部分都由一个键来表示,该键用于访问和管理数据以及数据本身。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>
因此,这里注册了两个新部分:购物车和目录数据。Magento\Checkout\CustomerData\Cart和Magento\Checkout\CustomerData\DirectoryData实现了Magento\Customer\CustomerData\SectionSourceInterface,并在getSectionData方法的返回值中提供实际数据。
部分更新是如何触发的?
当客户发送一些状态修改请求(POST、PUT、DELETE)时,Magento假定客户私有数据发生了变化。为了最小化服务器负载,开发者应在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.js和magento2ce/app/code/Magento/Customer/view/frontend/web/js/customer-data.js。
在最后,为ajaxComplete和submit注册了两个事件处理器。这意味着当任何表单(使用POST或PUT方法)提交到服务器,或当JavaScript发送AJAX、POST或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请求来更新?
此外,还有两个注意事项
这里所描述的是内部实现,可能会更改,因此您只能安全地使用sections.xml,并期望在指定的POST或PUT或DELETE操作触发时更新部分。如果您确定确实需要更新某个部分,您始终可以执行类似以下操作
require('Magento_Customer/js/customer-data').reload(['cart'], false)
在Magento 2中,Section.xml文件是什么?
随着互联网和技术的日益普及,设计、布局和代码也发生了多项变化和增强,以提供更好的用户体验。此外,Magento巧妙地采用了Knockout JS、AJAX等其他附加功能,允许Web应用程序异步地从服务器发送和检索数据,而无需刷新或重新加载。这种技术有助于减少服务器请求,并通过仅重新加载网页的一部分或某个部分来节省时间。例如,我们在Magento 2中有一个扩展提供了Ajax登录功能,并且我们希望在用户成功登录到他们的账户后恢复旧的商品车项。为此,我们只需要刷新迷你商品车,而不是整个页面。默认情况下,Magento 2在两边存储数据,因此如果我们想要刷新某个部分,我们也需要更新浏览器的本地存储数据。
如何在Magento 2中实现Section.xml文件?
为此,首先需要在以下路径创建“di.xml”文件。app\code\Vendor\Extension\etc\di.xml 同样,首先需要在以下路径创建“di.xml”文件。app\code\Vendor\Extension\etc\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>
现在,在上面的代码中,我们仅在客户数据部分注册了购物车和目录数据。为此,我们需要在以下路径创建section.xml文件,使用以下代码:app\code\Vendor\Extension\etc\frontend\section.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="routername/controller/action">
<section name="cart"/>
</action>
</config>
因此,现在每次我们调用“ajaxlogin/index/getlogin”之类的操作时,Magento都会认为当前的购物车部分已经过时,并重新初始化购物车部分。您也可以通过使用*而不是操作来在每次请求时刷新购物车部分。
解释一下Magento 2中的客户数据管理?
在处理Magento 2时,您可能会频繁遇到异步的客户数据加载。例如,购物车重新加载、结账、登录以及一些其他操作都是通过AJAX完成的。为了处理这些数据,Magento开发团队提供了一个合适的接口,我们现在将概述这个接口。
当前模块的接口由js-module组成,由RequireJs上传,并且还有一个允许通过AJAX发送数据的后端接口。让我们以在默认的Magento 2主题中显示名称的模板为例。客户的名称是通过以下实现的代码来显示的:
<span data-bind="text: new String('<?php echo $block->escapeHtml(__('Welcome, %1!', '%1'));?>').replace('%1', customer().firstname)">
如您所见,以下代码中的模板被customer().firstname对象属性所替换。在下面的代码中,您将看到与客户对象相关的内容:
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app": {
"components": {
"customer": {
"component": "Magento_Customer/js/view/customer"
}
}
}
}
}
</script>
您可以在以下文章中找到更多关于js-scripts和模块连接语法的详细信息:“在Magento 2中的JavaScript集成技巧”。
如您所见,客户对象是在Magento_Customer/js/view/customer.js文件中创建的。
define([
'uiComponent',
'Magento_Customer/js/customer-data'
], function (Component, customerData) {
'use strict';
return Component.extend({
initialize: function () {
this._super();
this.customer = customerData.get('customer');
}
});
});
这意味着当前代码返回一个Component对象(我们将在下一篇文章中介绍uiComponent的定义),并覆盖了initialize方法。所有从服务器上传数据的魔法都在这个方法中完成。请注意以下字符串:
this.customer = customerData.get('customer'); this.customer = customerData.get('customer'); 其中customerData是一个RequireJs模块,并在Magento_Customer/js/customer-data.js中初始化。
目前我们所知道的是:我们从customerData.get(‘customer’)对象中获取客户数据。我们不仅可以将“customer”传递到get方法中,还可以传递其他参数。
但是,我们有一些关于customerData使用的问题
从哪里获取数据,可以传递哪些参数到customerData.get();是否可以添加自己的参数到customerData.get();所以,让我们逐一考虑这些问题。
如果您在浏览器中启用调试模式并尝试将产品添加到购物车,您会发现一个相当常见的现象:会向服务器发送多个AJAX查询。但是,如果您重新加载页面,您会发现最初购物车是空的,但在页面加载过程中,购物车会被重新加载,并且之前添加的所有产品都会出现在其中。这种购物车行为告诉我们,在主页面加载完成后,会异步加载购物车数据。
然而,如果您启用调试器,您可能看不到发送到服务器的AJAX查询。但我们刚刚看到数据是从某个地方上传的,请不要忘记,数据不应该与主页面一起发送,因为这可能会引起启用FPC时的问题。基本上,我们得出结论,数据应该从某个地方上传,但绝对不是从AJAX上传。所以我们可能会认为它们被存储在浏览器中。这是真的。
如果您查看“应用→本地存储”(针对Chrome浏览器)选项卡,您将看到这些数据
请查看“mage-cache-storage”部分。所有可以用于customerData对象的数据都存储在这个特定的部分中。如果您删除这个部分然后重新加载页面,您会注意到购物车中的所有产品都会消失。并且只有在您再次重新加载当前部分并添加一个产品到购物车时,它们才会出现。
Mage-cache-storage部分的结构是一个普通的JSON对象,在其顶层我们有参数名称,我们可以将其传递到customerData对象的get方法中。因此,我们最终处理了customerData的结构,但我们仍然有一个问题:所有这些数据是从浏览器中出现的,以及与这些数据相关的代码。
如果您再向购物车添加一个产品,您将能够看到以下服务器查询
https://url_base/customer/section/load/?sections=cart%2Cmessages&update_section_id=true&=1478514106235 1 https://url_base/customer/section/load/?sections=cart%2Cmessages&update_section_id=true&=1478514106235 如URL所示,我们向带有以下参数的Magento\Customer\Controller\Section\Load控制器发送请求:sections=cart%2Cmessages&update_section_id=true。这就是我们需要的控制器,它负责数据更新。这样我们就能更新任何部分。
您还可以根据需要创建自己的部分并使用它。您只需要在di.xml文件中进行以下操作来注册您的部分
<type name="Magento\Customer\CustomerData\SectionPoolInterface">
<arguments>
<argument name="sectionSourceMap" xsi:type="array">
<item name="your_module_data" xsi:type="string">\YourCompany_YourModule\Order\Plugin\Section</item>
</argument>
</arguments>
</type>
在以下代码中,类\YourCompany_YourModule\Order\Plugin\Section应该执行Magento\Customer\CustomerData\SectionSourceInterface接口。因此,现在获取所需信息真的非常容易
var dataObject = customerData.get('your_module_data');
var data = dataObject();
dataObject - 这是一个返回ko.observable()方法的对象,因此很容易将其嵌入knokountJs模板中。只需执行以下命令,即可更新浏览器存储中特定部分的数据
customerData.reload(['your_module_data']))
CustomerData提供了几个非常实用的数据处理方法,让我们指定它们
get(section) - 请见上文;set(section,data) - 插入数据;reload(sections) - 重新加载数据;invalidate(section) - 对无效数据进行标记,这是必要的,以重新加载数据。到目前为止一切都很正常,但数据有效性管理出现了问题,因为我们执行了试图不断修改数据的许多操作。因此,我们应该控制这些数据。一个可能的解决方案是在与更改相关的操作上挂一个事件。但你不认为这很麻烦,而且查找错误需要花费太多时间。因此,Magento开发团队发明了一种非常独特的数据有效性控制方法。让我们更详细地看看magento_customer/js/customer-data.js文件(这是一个初始化customerData的模块),特别是这些字符串
$(document).on('ajaxComplete', function (event, xhr, settings) {
var sections,
redirects;
if (settings.type.match(/post|put/i)) {
sections = sectionConfig.getAffectedSections(settings.url);
if (sections) {
customerData.invalidate(sections);
redirects = ['redirect', 'backUrl'];
if (_.isObject(xhr.responseJSON) && !_.isEmpty(_.pick(xhr.responseJSON, redirects))) {
return;
}
customerData.reload(sections, true);
}
}
});
As you can see there is a function, hanged on ajaxComplete event in document object, and this function constantly compares URL address and that’s why URL selects those sections that should be updated. It’s a very useful mechanism of data validity control. We can add some sections, that will be updated upon transition to a certain URL. For that purpose we should add sections.xml file to etc/frontend directory in our module:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
<action name="braintree/paypal/placeOrder">
<section name="cart"/>
<section name="checkout-data"/>
</action>
</config>
这个例子是从Braintree模块中获取的。我们注意到,在执行带有URL地址braintree/paypal/placeOrder的AJAX查询(POST,PUT)之后,购物车部分和结账数据部分将会被覆盖。值得一提的是,像消息这样的部分,在请求任何URL时都会被更新,因此当你在模块中使用AJAX查询时,请记住,除了你的请求外,至少还会执行另一个请求来更新部分。你可以使用GET方法代替POST,以避免这种情况。尽管看起来很复杂,但一旦你掌握了它,你将获得一个非常有灵活性的数据管理和AJAX查询工具。