Magento 2:按网站将城市地址属性设置为可选
由于Magento 2后台默认仅支持全局配置「city」地址属性的必填性,要实现网站维度的控制,可通过以下两种方法完成:
方法一:后端插件拦截验证逻辑(核心方案)
通过插件重写地址验证方法,根据当前网站ID动态调整「city」的必填规则:
创建自定义模块(若已有自定义模块可跳过此步)
新建模块Vendor_CustomerAddress,目录结构为app/code/Vendor/CustomerAddress,并添加必要的registration.php和module.xml文件。配置插件依赖注入
在app/code/Vendor/CustomerAddress/etc/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\Model\Address\AbstractAddress"> <plugin name="modify_city_required_validation" type="Vendor\CustomerAddress\Plugin\ModifyCityRequired" sortOrder="10"/> </type> </config>编写插件业务逻辑
创建app/code/Vendor/CustomerAddress/Plugin/ModifyCityRequired.php文件,实现验证拦截:<?php namespace Vendor\CustomerAddress\Plugin; use Magento\Customer\Model\Address\AbstractAddress; use Magento\Store\Model\StoreManagerInterface; class ModifyCityRequired { /** @var StoreManagerInterface */ private $storeManager; public function __construct(StoreManagerInterface $storeManager) { $this->storeManager = $storeManager; } public function afterValidate(AbstractAddress $subject, $validationResult) { // 指定需要将「city」设为可选的网站ID,支持多个网站时用数组判断 $targetWebsiteIds = [2]; $currentWebsiteId = $this->storeManager->getStore()->getWebsiteId(); if (in_array($currentWebsiteId, $targetWebsiteIds) && is_array($validationResult)) { // 移除「city」必填的错误提示 unset($validationResult['city']); // 若错误数组为空,返回true表示验证通过 return empty($validationResult) ? true : $validationResult; } return $validationResult; } }部署并清理缓存
执行以下命令使配置生效:bin/magento setup:di:compile bin/magento cache:clean bin/magento cache:flush
方法二:前端验证适配(提升用户体验)
若前端地址表单仍保留「city」的必填校验,需同步调整前端逻辑:
修改模板文件
将vendor/magento/module-customer/view/frontend/templates/address/edit.phtml复制到自定义主题目录(如app/design/frontend/Vendor/Theme/Magento_Customer/templates/address/edit.phtml),找到「city」字段的HTML代码,根据网站ID动态移除required-entry类:<?php $currentWebsiteId = $block->getStore()->getWebsiteId(); ?> <div class="field city <?= in_array($currentWebsiteId, [2]) ? '' : 'required' ?>"> <label class="label" for="city"><span><?= $block->escapeHtml(__('City')) ?></span></label> <div class="control"> <input type="text" name="city" value="<?= $block->escapeHtmlAttr($block->getAddress()->getCity()) ?>" title="<?= $block->escapeHtmlAttr(__('City')) ?>" class="input-text <?= in_array($currentWebsiteId, [2]) ? '' : 'required-entry' ?>" id="city" <?= $block->getFieldParams() ?>> </div> </div>JavaScript动态调整验证
若不想修改模板,可通过JS动态更新验证规则:require(['jquery', 'mage/validation'], function($) { var currentWebsiteId = <?= $block->getStore()->getWebsiteId() ?>; if (currentWebsiteId === 2) { $('#city').removeClass('required-entry'); $('#form-validate').validation('refresh'); } });
内容的提问来源于stack exchange,提问作者Denis2310

