Magento 2:结账前动态修改自定义地址属性is_required值
Magento 2:根据客户类型动态设置自定义地址属性为必填项
需求:结账前针对企业客户,将自定义地址属性gui_number的is_required从false改为true,使其成为必填字段。已尝试编写插件修改属性值,通过Xdebug确认方法执行且值已修改,但前端结账地址表单仍显示为可选,未达预期效果,寻求正确实现方案。
已尝试的实现代码
插件配置
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Customer\Model\Address"> <plugin name="customer_adjust_address_attributes" type="CustomModule\Customer\Plugin\Model\Address" disabled="false"/> </type> </config>
插件方法
public function afterGetAttributes(DefaultAddress $subject, $result) { $customerType = $this->customerSession->getCustomer()->getCustomerType(); if ($customerType == PhoenixCustomerHelper::CUSTOMER_TYPE_BUSINESS) { foreach ($result as &$attribute) { if ($attribute->getName() == 'gui_number') { $attribute->setIsRequired('1'); } } } return $result; }
正确实现方案
1. 调整前端结账表单的字段配置
结账地址表单的渲染逻辑由Magento\Checkout\Block\Checkout\LayoutProcessor控制,需通过插件修改该类的process方法,针对企业客户动态设置gui_number为必填:
前端插件配置(app/code/CustomModule/Customer/etc/frontend/di.xml)
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> <plugin name="custom_checkout_address_layout_processor" type="CustomModule\Customer\Plugin\Block\Checkout\LayoutProcessor" sortOrder="10"/> </type> </config>
插件代码
<?php namespace CustomModule\Customer\Plugin\Block\Checkout; use Magento\Checkout\Block\Checkout\LayoutProcessor; use Magento\Customer\Model\Session as CustomerSession; use CustomModule\Customer\Helper\PhoenixCustomerHelper; class LayoutProcessor { protected $customerSession; protected $customerHelper; public function __construct( CustomerSession $customerSession, PhoenixCustomerHelper $customerHelper ) { $this->customerSession = $customerSession; $this->customerHelper = $customerHelper; } public function afterProcess(LayoutProcessor $subject, $result) { $customer = $this->customerSession->getCustomer(); if (!$customer->getId()) { return $result; } if ($customer->getCustomerType() === $this->customerHelper::CUSTOMER_TYPE_BUSINESS) { // 修改账单地址字段规则 $billingFieldPath = 'components/checkout/children/steps/children/billing-step/children/payment/children/payments-list/children/billing-address-form/children/form-fields/children/gui_number'; if (isset($result[$billingFieldPath])) { $result[$billingFieldPath]['validation']['required-entry'] = true; $result[$billingFieldPath]['config']['notice'] = __('此字段为必填项'); } // 修改送货地址字段规则 $shippingFieldPath = 'components/checkout/children/steps/children/shipping-step/children/shippingAddress/children/shipping-address-fieldset/children/gui_number'; if (isset($result[$shippingFieldPath])) { $result[$shippingFieldPath]['validation']['required-entry'] = true; $result[$shippingFieldPath]['config']['notice'] = __('此字段为必填项'); } } return $result; } }
2. 加强后端验证
仅修改前端无法防止绕过验证提交,需在后端地址保存时强制验证:
后端插件配置(app/code/CustomModule/Customer/etc/di.xml)
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Customer\Model\Address"> <plugin name="custom_customer_address_validate" type="CustomModule\Customer\Plugin\Model\AddressValidate" sortOrder="10"/> </type> </config>
插件代码
<?php namespace CustomModule\Customer\Plugin\Model; use Magento\Customer\Model\Address; use Magento\Customer\Model\Session as CustomerSession; use CustomModule\Customer\Helper\PhoenixCustomerHelper; class AddressValidate { protected $customerSession; protected $customerHelper; public function __construct( CustomerSession $customerSession, PhoenixCustomerHelper $customerHelper ) { $this->customerSession = $customerSession; $this->customerHelper = $customerHelper; } public function beforeValidate(Address $subject) { $customer = $this->customerSession->getCustomer(); if ($customer->getId() && $customer->getCustomerType() === $this->customerHelper::CUSTOMER_TYPE_BUSINESS) { $attribute = $subject->getResource()->getAttribute('gui_number'); if ($attribute) { $attribute->setIsRequired(true); } } } }
原方案无效原因
原方案修改的Magento\Customer\Model\Address::getAttributes返回的属性对象,不会同步到结账表单的渲染配置中——结账表单的字段规则是由LayoutProcessor独立生成的,与地址模型的属性实例分离,因此前端不会感知到属性is_required的变化。
内容的提问来源于stack exchange,提问作者Denis2310
相关产品推荐
相关产品推荐

