0

0

Shopware订单对象中获取产品自定义字段的正确方法

DDD

DDD

发布时间:2025-12-01 12:06:27

|

886人浏览过

|

来源于php中文网

原创

shopware订单对象中获取产品自定义字段的正确方法

本文详细阐述了在Shopware订单对象中,如何正确获取产品自定义字段的策略。针对常见的语言依赖性问题,教程指出通过调整关联路径为`lineItems.product.default`,而非`translations`,可以有效访问非语言相关的自定义字段,并提供了具体的代码示例和最佳实践,帮助开发者高效集成自定义数据。

在Shopware的开发实践中,经常需要在订单处理流程中访问与产品相关的自定义字段(Custom Fields)。例如,一个产品可能有一个名为emakers_custom_field_warehouse_name的自定义字段,用于存储其所属仓库的名称。当订单生成后,开发者需要从订单行项目(Line Items)中获取该产品及其自定义字段信息。然而,直接尝试获取自定义字段可能会遇到因语言依赖性而导致的数据缺失问题。

问题描述与初始尝试

在Shopware中,产品数据通常包含多语言翻译。自定义字段的配置也可能分为语言相关和非语言相关两种。当通过订单对象检索产品信息时,如果自定义字段是非语言相关的,但查询关联却指向了翻译实体,就可能无法正确获取这些字段。

以下是一个常见的初始查询尝试,旨在获取订单及其行项目中的产品翻译信息:

use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SalesChannel\Repository\SalesChannelRepositoryInterface; // 假设通过销售渠道仓库获取订单

// ... 在一个服务或控制器中 ...

public function getOrderWithProductCustomFields(string $orderId): ?OrderEntity
{
    $criteria = new Criteria();
    $criteria->addFilter(new EqualsFilter('id', $orderId));
    $criteria->addAssociations([
        'deliveries.shippingOrderAddress.salutation',
        'deliveries.shippingOrderAddress.country',
        'orderCustomer.customer.group',
        'lineItems.product.translations', // 初始尝试,关联产品翻译
    ]);

    // 假设通过 orderRepository 注入
    $orderObject = $this->orderRepository->search($criteria, Context::createDefaultContext())->first();

    if ($orderObject) {
        $firstLineItem = $orderObject->getLineItems()->first();
        if ($firstLineItem && $firstLineItem->getProduct()) {
            // 尝试获取自定义字段,此时可能为空
            $customFields = $firstLineItem->getProduct()->getCustomFields();
            // 尝试访问产品翻译,会报错:Attempted to call an undefined method named "getProductTranslations"
            // $firstLineItem->getProduct()->getProductTranslations();
        }
    }
    return $orderObject;
}

在这种情况下,即使产品数据中确实存在emakers_custom_field_warehouse_name这样的自定义字段,通过$firstLineItem->getProduct()->getCustomFields()获取到的结果也可能是空的。进一步尝试直接调用getProductTranslations()方法也会导致错误,因为ProductEntity本身并没有直接暴露这个方法来获取所有翻译集合。

解决方案:关联默认产品数据

问题的核心在于,非语言相关的自定义字段通常存储在产品实体(ProductEntity)的默认数据中,而不是其语言翻译实体(ProductTranslationEntity)中。当通过'lineItems.product.translations'关联时,Shopware会加载与当前上下文语言匹配的产品翻译数据,而这些数据可能不包含非语言相关的自定义字段。

正确的做法是关联'lineItems.product.default'。这个关联会确保我们获取到产品实体的默认数据,其中就包含了那些不依赖于特定语言的自定义字段。

美图AI开放平台
美图AI开放平台

美图推出的AI人脸图像处理平台

下载

以下是修正后的Criteria配置:

use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Checkout\Order\OrderEntity; // 引入OrderEntity
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; // 引入EntityRepository

// ... 在一个服务或控制器中 ...
class OrderService
{
    private EntityRepository $orderRepository;

    public function __construct(EntityRepository $orderRepository)
    {
        $this->orderRepository = $orderRepository;
    }

    public function getOrderWithProductCustomFields(string $orderId): ?OrderEntity
    {
        $criteria = new Criteria();
        $criteria->addFilter(new EqualsFilter('id', $orderId));
        $criteria->addAssociations([
            'deliveries.shippingOrderAddress.salutation',
            'deliveries.shippingOrderAddress.country',
            'orderCustomer.customer.group',
            'lineItems.product.default', // 关键修改:关联产品默认数据
        ]);

        $orderObject = $this->orderRepository->search($criteria, Context::createDefaultContext())->first();

        if ($orderObject) {
            $firstLineItem = $orderObject->getLineItems()->first();
            if ($firstLineItem && $firstLineItem->getProduct()) {
                // 现在可以正确获取自定义字段
                $customFields = $firstLineItem->getProduct()->getCustomFields();

                // 示例:访问特定自定义字段
                if ($customFields && isset($customFields['emakers_custom_field_warehouse_name'])) {
                    $warehouseName = $customFields['emakers_custom_field_warehouse_name'];
                    // ... 处理 $warehouseName ...
                }
                return $orderObject;
            }
        }
        return null;
    }
}

通过将关联从'lineItems.product.translations'改为'lineItems.product.default',$firstLineItem->getProduct()->getCustomFields()现在将能成功返回包含emakers_custom_field_warehouse_name在内的所有非语言相关自定义字段。

深入理解Shopware数据模型:default 与 translations

在Shopware的实体关联中:

  • .translations: 用于加载当前上下文语言下的实体翻译数据。如果自定义字段被配置为“可翻译”,则它们会存储在翻译实体中。但如果自定义字段是全局的、非语言相关的,它们则不会出现在这里。
  • .default: 通常指向实体的主数据或默认数据。对于产品而言,这包含了产品的基础信息以及那些不依赖于特定语言的自定义字段。当自定义字段不是可翻译的(即在Shopware后台创建时未勾选“可翻译”选项),它们就会存储在这里。

因此,当需要访问那些全局的、非语言相关的自定义字段时,应优先考虑关联.default。如果确实需要访问特定语言下的可翻译自定义字段,则需要确保该自定义字段在后台被配置为可翻译,并且在查询时使用正确的语言上下文。

实践建议

  1. 明确自定义字段类型: 在Shopware后台创建自定义字段时,要清楚其是“可翻译”还是“不可翻译”。这决定了在代码中如何正确地通过关联来访问它们。
  2. 选择合适的关联路径:
    • 对于非语言相关的自定义字段,使用.default关联。
    • 对于语言相关的自定义字段,如果需要特定语言的翻译,可以使用.translations并确保上下文语言正确。
  3. 考虑性能: 过多的关联会增加数据库查询的复杂度和数据量。只关联你真正需要的数据,避免不必要的关联。
  4. 上下文管理: Context::createDefaultContext()通常用于获取系统默认上下文。如果你的操作需要在特定的销售渠道或语言环境下执行,请确保使用相应的上下文对象。
  5. 空值检查: 始终对获取到的实体和自定义字段数组进行空值检查,以避免潜在的null引用错误。

通过理解Shopware的数据关联机制,特别是default和translations的区别,开发者可以更精确、高效地在订单对象中获取所需的产品自定义字段,从而构建健壮的Shopware应用程序。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

232

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

437

2024.03.01

default gateway怎么配置
default gateway怎么配置

配置default gateway的步骤:1、了解网络环境;2、获取路由器IP地址;3、登录路由器管理界面;4、找到并配置WAN口设置;5、配置默认网关;6、保存设置并退出;7、检查网络连接是否正常。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

220

2023.12.07

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

352

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2075

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

347

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

324

2023.10.09

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

1

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号