Я пытаюсь изучить API Laravel и ломаю голову над тем, что должно быть простой проблемой. У меня есть одна таблица базы данных с данными о продажах, возвращающая эту коллекцию ресурсов API.
{
"id": "1",
"itemCode": "item1",
"date": "2024-06-10",
"qty": "1"
},
{
"id": "2",
"itemCode": "item1",
"date": "2024-06-10",
"qty": "10"
},
{
"id": "3",
"itemCode": "item1",
"date": "2024-06-08",
"qty": "5"
},
{
"id": "4",
"itemCode": "item2",
"date": "2024-06-10",
"qty": "2"
}
Я пытаюсь сгруппировать их по itemCode и дате, но сохраняю все данные в столбце подуровня «подробности».
Я пытаюсь достичь этого результата:
{
"itemCode": "item1",
"date": "2024-06-10",
"details":
[
{"id": "1", "qty": "1"},
{"id": "2", "qty": "10"},
]
},
{
"itemCode": "item1",
"date": "2024-06-08",
"details":
[
{"id": "3", "qty": "5"},
]
},
{
"itemCode": "item2",
"date": "2024-06-08",
"details":
[
{"id": "4", "qty": "2"},
]
}
Мне удалось достичь ожидаемых результатов с первого раза в моем контроллере
$summary = orders::select('id','date', 'itemCode', 'qty')
->groupBy('id','date', 'itemCode', 'qty')
return orderGroupResource::collection($summary);
И на моем ресурсе:
return [
'date' => $this->date,
'itemCode' => $this->itemCode,
'details' =>
detailResource::collection(order::where('date', $this->date)
->where('itemCode', $this->itemCode)
->get()),
];
Однако в результате для каждой группы создается один новый запрос, и кажется, что его можно решить более эффективным способом.
Подробности – это исходные нефильтрованные данные. Из этих данных я пытаюсь получить ключ верхнего уровня для каждого элемента и дня. Поэтому, когда интерфейс выполняет итерацию возвращенного массива, он сначала получает каждый элемент и день, а затем все заказы в массиве подуровней.






Есть несколько способов сделать это. Поскольку вы используете ресурсы, вы можете поиграть с этим
ПодробноРесурс
public function toArray($request)
{
return [
'id' => $this->id,
'qty' => $this->qty,
];
}
В ресурсе группы заказов
$grouped = $this->resource->groupBy(function ($item) {
return $item['itemCode'] . '-' . $item['date'];
}); # expined down
return $grouped->map(function ($group) {
$first = $group->first();
return [
'itemCode' => $first->itemCode,
'date' => $first->date,
'details' => DetailResource::collection($group->values()),
];
})->values();
Группировка элементов по
itemCodeиdateдля создания уникального ключа, позволяющего методу groupBy эффективно группировать элементы.
В контроллере
public function getSummary()
{
$orders = Order::all();
return new OrderGroupResource($orders);
}
Это похоже на то, чего я пытаюсь достичь, но получаю ошибку: «Вызов неопределенного метода Illuminate\Database\Eloquent\Builder::map()»
@Йохан, ты добавил это $orders = Order::all(); return new OrderGroupResource($orders); В контроллере
и убедитесь, что $orders не пуст
Конечно, я перенастраивал коллекцию OrderGroupResource. Также мне нужно было добавить ->toArray() после ->values() в OrderGroupResource. Большое спасибо за вашу помощь!
что означают детали, у вас есть таблица order_items? или как узнать подробности