You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:15:06