Laravel Eloquent - 合并两个 Eloquent 模型查询结果(非集合)

6

我有一个库存移动表,显示了产品的历史记录(接收、移动位置等)。

我有两个查询,分别计算(通过聚合求和):

  1. 原始接收数量。
  2. 当前活跃数量(在物品移动后)。

这两个查询都返回相同模型的集合。它们总是具有相同数量的结果,并且产品ID始终相同。唯一不同的部分是接收/活跃数量,我希望能将单个记录合并到新的集合中。例如:

查询1返回的单个记录:

0 => StockMovement {#1602 ▼
  #original: array:2 [▼
    "live_qty" => "8"
    "product_id" => "2606598e-4150-461a-9e91-10d67cce8daa"
  ]
}

查询2中的单条记录;

0 => StockMovement {#1602 ▼
  #original: array:2 ["received_qty" => "15"
    "product_id" => "2606598e-4150-461a-9e91-10d67cce8daa"
  ]
}

我试图得到一个合并的结果,它的样子如下所示:

0 => StockMovement {#1602 ▼
  #original: array:3 [▼
    "received_qty" => "15"
    "live_qty" => "8"
    "product_id" => "2606598e-4150-461a-9e91-10d67cce8daa"
  ]
}

我希望以一种不将Product对象转换为数组的方式来完成此操作,因为我需要其中嵌入的关系。

目前,我已经通过以下方式进行了hack:

$live = $this->liveQtyCollection();
$merged = $this->receivedQtyCollection()->map(function(StockMovement $received) use($live){
    $line = $live->where('product_id', $received->product_id)->first();
    return arrayToObject(array_merge($received->toArray(), $line->toArray()));
});
return $merged;

arrayToObject 函数,可以递归地将数组转换回对象,以便我可以像在其原始集合时一样使用箭头选择器,但我确定一定有更好的方法!

我尝试了:

  • 合并(Merge)
  • 联合(Union)
  • 全部(All)

我的最终目标是能够按以下方式使用生成的集合:

@foreach($stockMovements as $stockMovement)
    {{ $stockMovement->id }}
    {{ $stockMovement->live_qty }}
    {{ $stockMovement->received_qty }}
@endforeach

Eloquent 返回的所有多结果集都是 Illuminate\Database\Eloquent\Collection 对象的实例。为什么说不是 collections? - Jafar Akhondali
我认为集合是“优美模型结果的集合”,我想确保不将stockMovement模型拆分为数组或纯集合,即我想保留其所有关系功能,例如$ stockMovement-> product-> title,其中stockMovement属于某个产品,通过product_id。 - Adam Lambert
我认为你可以尝试这种方法:https://laravel.com/docs/5.8/eloquent-relationships - loic.lopez
@loic.lopez 谢谢。我已经知道什么是关系了。我只是试图在保持关系完整的同时合并上述两个查询。如果在合并之前将其转换为数组,则关系将丢失。 - Adam Lambert
3个回答

8
你可以使用以下代码:
$collection = collect();
$cars = Car::all();
$bikes = Bike::all();

foreach ($cars as $car)
    $collection->push($car);

foreach ($bikes as $bike)
    $collection->push($bike);

Source


1

我知道你在问题中提到了你不是指集合,并且你已经尝试过合并,但为了讨论的完整性,我想把我的答案加入进来,因为这正好适用于我需要的情况;合并两个模型调用的响应。

$quote = \App\AllQuotes::withoutGlobalScopes()->find($quote_id);
$settings = \App\Settings::findOrFail(1);
$settings = collect($settings);
$quote = collect($quote);
$merged = $quote->merge($settings);

return $merged;

您需要使用collect助手将模型响应首先封装为集合,然后才能将它们合并在一起。输出随后将其视为逻辑联接,在单个输出中维护来自两个模型的数据。


0
你可以这样做:
$live = $this->liveQtyCollection()->keyBy('product_id')
$merged = $this->receivedQtyCollection()->map(function(StockMovement $received) use($live){
    $received->live_qty = $live->get($received->product_id)->live_qty ?? null;
    return $received;
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接