【问题标题】:Query for getting OrderLineItems in Shopware 6 fails due to missing column 'order_line_item.order.order_line_item_version_id'由于缺少列 \'order_line_item.order.order_line_item_version_id\',在 Shopware 6 中获取 OrderLineItems 的查询失败
【发布时间】:2023-02-01 13:37:51
【问题描述】:

我正在尝试获取 Shopware 6.4.18.1 中的所有 OrderLineItems,它们是某个制造商的产品并且:

  • 已支付(如果使用预付款)
  • 或者:
    • 已部分支付
    • 正在付款
    • 付款打开

以下代码:

<?php

declare(strict_types=1);

namespace MyBundle\App\Query\OrderLineItem;

use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\PrePayment;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\AndFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NorFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;

class OrderLineItemQuery
{
    public const PAID_STATE = 'paid';
    public const PAID_PARTIALLY_STATE = 'paid_partially';
    public const IN_PROGRESS_STATE = 'in_progress';
    public const OPEN_STATE = 'open';

    protected EntityRepository $orderLineItemRepository;

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

    public function getOrderLineItemsByManufacturer(string $manufacturerId): EntityCollection
    {
        $criteria = new Criteria();

        // default associations needed for following procedures
        $criteria->addAssociations([
            'order.deliveries.shippingOrderAddress.country',
            'order.deliveries.shippingOrderAddress.salutation',
            'order.orderCustomer.customer.salutation',
            'order.salesChannel',
            'order.transactions.stateMachineState',
            'order.transactions.paymentMethod',
            'product.manufacturer',
        ]);

        $criteria->addFilter(
            // only take manufacturer products
            new EqualsFilter('product.manufacturer.id', $manufacturerId),
            // exclude unpaid prepayment orders
            new OrFilter([
                new EqualsFilter('order.transactions.stateMachineState.technicalName', self::PAID_STATE),
                // removing the filters inside here fixes the problem
                new AndFilter([
                    new NorFilter([
                        new EqualsFilter('order.transactions.paymentMethod.handlerIdentifier', PrePayment::class),
                    ]),
                    new OrFilter([
                        new EqualsFilter('order.transactions.stateMachineState.technicalName', self::PAID_PARTIALLY_STATE),
                        new EqualsFilter('order.transactions.stateMachineState.technicalName', self::IN_PROGRESS_STATE),
                        new EqualsFilter('order.transactions.stateMachineState.technicalName', self::OPEN_STATE),
                    ]),
                ]),
            ])
        );

        return $this->orderLineItemRepository->search($criteria, Context::createDefaultContext())->getEntities();
    }
}

但它只返回错误:

在 Exception.php 第 18 行中:
SQLSTATE [42S22]:未找到列:1054“字段列表”中的未知列“order_line_item.order.order_line_item_version_id”

删除 AndFilter 内的所有内容似乎可以消除错误,但我需要从选择预付款作为付款方式但尚未付款的订单中排除 OrderLineItems。

我应该如何更改查询以使其工作?

【问题讨论】:

    标签: shopware shopware6


    【解决方案1】:

    我认为这里的问题可能是循环引用。由于您查询的主要是订单的关联,我建议您改用 order.repository 将查询基于 order 表。通过被动添加 lineItems 关联,您可以迭代 OrderEntity 实例并通过调用 getLineItems() 收集所有对应的行项目。

    $criteria = new Criteria();
    
    // default associations needed for following procedures
    $criteria->addAssociations([
        'deliveries.shippingOrderAddress.country',
        'deliveries.shippingOrderAddress.salutation',
        'orderCustomer.customer.salutation',
        'salesChannel',
        'transactions.stateMachineState',
        'transactions.paymentMethod',
    ]);
    
    /**
     * Get an association `lineItems`. (is added by calling the getter as well)
     * Add a filter specifically for that association.
     * Optionally, if you need `product` and `manufacturer` data, 
     * add them as additional associations.
     */
    $criteria->getAssociation('lineItems')
        ->addFilter(
            new EqualsFilter('product.manufacturer.id', $manufacturerId)
        )
        ->addAssociation('product.manufacturer');
    
    $criteria->addFilter(
        new OrFilter([
            new EqualsFilter('transactions.stateMachineState.technicalName', self::PAID_STATE),
            new AndFilter([
                new NorFilter([
                    new EqualsFilter('transactions.paymentMethod.handlerIdentifier', PrePayment::class),
                ]),
                new OrFilter([
                    new EqualsFilter('transactions.stateMachineState.technicalName', self::PAID_PARTIALLY_STATE),
                    new EqualsFilter('transactions.stateMachineState.technicalName', self::IN_PROGRESS_STATE),
                    new EqualsFilter('transactions.stateMachineState.technicalName', self::OPEN_STATE),
                ]),
            ]),
        ])
    );
    
    $orders = $this->orderRepository->search($criteria, Context::createDefaultContext())->getEntities();
    
    $lineItems = new OrderLineItemCollection();
    /** @var OrderEntity $order */
    foreach ($orders as $order) {
        $lineItems->merge($order->getLineItems());
    }
    
    return $lineItems;
    

    【讨论】:

    • 谢谢你的代码,但如果我理解正确的话,如果一个订单包含 2 个产品,一个来自请求的制造商,另一个来自另一个制造商,这两种产品仍将合并到$lineItems,对吗?
    • 不,通过调用 getLineItems() 检索到的 OrderLineItemCollection 应该只包含与来自一个制造商的产品相关联的行项目。 Criteria 变成了带有连接链的 SQL 查询,从 order_line_item 记录到 manufacturer 表。然后在 WHERE 语句中使用连接的表。因此,最终结果中不应包含未选择的值。顺便说一句,您可能想改用lineItems.product.manufacturerId,少加入一个;)
    • 谢谢!有没有办法检测循环引用或抛出早期异常?从上面使用的代码中,我没有看到一个。
    • 是的,这只是我的猜测。这似乎有点奇怪,我还没有看到它试图在一个完全不同的实体上使用一个实体的版本字段。我认为如果你有一个从源中删除两次的关联,然后又在源上有一个关联,可能是自动加载或其他东西,那么这可能会发生。这是一个相当繁重的查询,因此如果不进行进一步调查,很难说出这会发生在哪里。
    • 可悲的是,它包括不是来自给定制造商的产品。我会在-&gt;merge()前加个支票
    猜你喜欢
    • 2019-11-02
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 2022-10-02
    • 2020-06-02
    • 1970-01-01
    • 2014-02-25
    • 2011-12-29
    相关资源
    最近更新 更多