我有这个查询:
Order::find('1234')->refunds()->with('orderItems')->get()
这会导致内存不足错误耗尽 256 MB 来获取一行,而加载的items
也只有一行。
如果我尝试这个,我没有问题:
Order::find('1234')->refunds->first()->orderItems
只有当我急切加载时。
我的枢轴定义:
public function items(): BelongsToMany
{
return $this->belongsToMany(OrderItem::class)
->using(OrderItemRefund::class)
->withPivot([
'amount',
]);
}
当我查看它在跟踪中失败的查询时,我看到以下内容:
SELECT
`order_items`.*,
`order_item_refund`.`refund_id` AS `pivot_refund_id`,
`order_item_refund`.`order_item_id` AS `pivot_order_item_id`,
`order_item_refund`.`amount` AS `pivot_amount`
FROM
`order_items`
INNER JOIN `order_item_refund` ON `order_items`.`id` = `order_item_refund`.`order_item_id`
WHERE
`order_item_refund`.`refund_id` IN ( 0 )
AND `order_items`.`deleted_at` IS NULL
关键问题似乎是 Eloquent 如何在内部构建部件refund_id IN ( 0 )
,而它没有为数据透视表添加相关的refund_id
值。如果我在数据库上将其作为原始查询运行,它将返回连接满足的所有记录,而不按refund_id
过滤,这只会产生一条记录。
选中时,透视查询的绑定为空:
{
bindings: [],
connectionName: mysql,
executionTimeMs: 8663.32
}
但是,Eloquent 查询的所有绑定在此之前都会执行,直到透视具有预期值。
我还进一步发现,这会影响所有使用BelongsToMany
的模型中的所有关系。代码在升级到 Laravel 8 后才开始运行(特别是我们在 v8.83.14 上)。
我尝试将 Laravel 和 Doctrine 降级到早期的次要版本,同时仍然保留在 v8 上,但这没有帮助。
在 Laravel 6 中,主键现在被转换为整数,除非明确设置为字符串。
https://laravel.com/docs/6.x/upgrade#eloquent-primary-key-type
发生这种情况的原因是因为我们从 Laravel 5.4 升级到 Laravel 8 并且具有基于字符串的主键。
在相关模型上设置以下内容解决了该问题:
protected $keyType = 'string';