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

求助:Magento2自定义配送方式附加数据无法保存至报价与订单

嘿,刚上手Magento2遇到这种自定义配送方式的附加数据保存问题太正常了,我来一步步给你捋清楚怎么搞定!

第一步:确保前端表单数据能正确提交到后端

首先得让你添加的附加表单字段数据在结账时被一起提交。在你的自定义配送方式的前端模板(比如 view/frontend/templates/shipping_method/your_custom_method.phtml)里,把表单字段放在结账配送地址表单的范围内,并且字段名最好用统一前缀,方便后端识别:

<div class="custom-delivery-field">
    <label for="delivery_special_note"><?= __('Special Delivery Instructions') ?></label>
    <input type="text" 
           name="shipping_additional[delivery_note]" 
           id="delivery_special_note" 
           class="input-text" />
</div>

记得要通过布局XML把这个模板正确挂载到配送方式的渲染区块里,确保用户选择你的配送方式时能看到这个表单。

第二步:拦截配送信息保存,把数据存到Quote里

Magento2的结账流程中,Magento\Checkout\Model\ShippingInformationManagement::saveShippingInformation 是保存配送信息的核心方法,我们可以用插件来拦截它,获取前端提交的附加数据并存到Quote中:

  1. 先在你的模块 etc/di.xml 里注册插件:
<type name="Magento\Checkout\Model\ShippingInformationManagement">
    <plugin name="save_custom_delivery_quote_data" 
            type="YourVendor\YourModule\Plugin\SaveCustomDeliveryQuoteData" />
</type>
  1. 编写插件类:
<?php
namespace YourVendor\YourModule\Plugin;

use Magento\Checkout\Model\ShippingInformationManagement;
use Magento\Quote\Model\QuoteRepository;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\ObjectManagerInterface;

class SaveCustomDeliveryQuoteData
{
    protected $quoteRepository;
    protected $request;
    protected $objectManager;

    public function __construct(
        QuoteRepository $quoteRepository,
        RequestInterface $request,
        ObjectManagerInterface $objectManager
    ) {
        $this->quoteRepository = $quoteRepository;
        $this->request = $request;
        $this->objectManager = $objectManager;
    }

    public function beforeSaveShippingInformation(
        ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    ) {
        // 拿到前端提交的附加数据
        $additionalShippingData = $this->request->getParam('shipping_additional');
        
        if (!empty($additionalShippingData['delivery_note'])) {
            $quote = $this->quoteRepository->getActive($cartId);
            
            // 用扩展属性存数据(不用改数据库表,符合Magento规范)
            $quoteExtension = $quote->getExtensionAttributes();
            if (!$quoteExtension) {
                $quoteExtension = $this->objectManager->create(
                    \Magento\Quote\Api\Data\QuoteExtensionInterface::class
                );
            }
            $quoteExtension->setDeliveryNote($additionalShippingData['delivery_note']);
            $quote->setExtensionAttributes($quoteExtension);
            
            $this->quoteRepository->save($quote);
        }
        
        return [$cartId, $addressInformation];
    }
}
  1. 别忘了在 etc/extension_attributes.xml 里定义Quote的扩展属性,这样Magento能识别这个字段:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\QuoteInterface">
        <attribute code="delivery_note" type="string" />
    </extension_attributes>
    <!-- 同时提前定义Order的扩展属性,后面同步用 -->
    <extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
        <attribute code="delivery_note" type="string" />
    </extension_attributes>
</config>

第三步:把Quote里的附加数据同步到Order

当Quote转换为Order时,我们需要把刚才存在Quote里的数据复制到Order中,这里用Observer监听sales_convert_quote_to_order事件:

  1. 在 etc/events.xml 里注册Observer:
<event name="sales_convert_quote_to_order">
    <observer name="convert_custom_delivery_to_order" 
              instance="YourVendor\YourModule\Observer\ConvertCustomDeliveryToOrder" />
</event>
  1. 编写Observer类:
<?php
namespace YourVendor\YourModule\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\ObjectManagerInterface;

class ConvertCustomDeliveryToOrder implements ObserverInterface
{
    protected $objectManager;

    public function __construct(ObjectManagerInterface $objectManager)
    {
        $this->objectManager = $objectManager;
    }

    public function execute(Observer $observer)
    {
        $quote = $observer->getQuote();
        $order = $observer->getOrder();
        
        // 从Quote扩展属性拿到数据
        $deliveryNote = $quote->getExtensionAttributes()->getDeliveryNote();
        
        if ($deliveryNote) {
            // 把数据存到Order的扩展属性里
            $orderExtension = $order->getExtensionAttributes();
            if (!$orderExtension) {
                $orderExtension = $this->objectManager->create(
                    \Magento\Sales\Api\Data\OrderExtensionInterface::class
                );
            }
            $orderExtension->setDeliveryNote($deliveryNote);
            $order->setExtensionAttributes($orderExtension);
            
            // 如果你给sales_order表加了自定义字段,也可以直接这么存:
            // $order->setDeliveryNote($deliveryNote);
        }
        
        return $this;
    }
}

额外注意点

  • 如果你不想用扩展属性,而是想直接在数据库表中存储,可以创建安装脚本给 quote 和 sales_order 表添加自定义字段(比如 delivery_note),然后在代码中直接用 $quote->setDeliveryNote(...) 和 $order->setDeliveryNote(...) 来存取。
  • 做完所有修改后,一定要执行 bin/magento cache:flush 清除缓存,确保插件和Observer被正确加载。
  • 可以在前端加一些表单验证,比如限制输入长度,提升用户体验。

这样操作下来,你的自定义配送方式的附加数据就能顺利保存到Quote和Order里啦!

内容的提问来源于stack exchange,提问作者Andrew Smith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:29:27