У меня есть коллекция объектов, извлеченных из моей БД с помощью Eloquent ORM от Laravel (я не использую Laravel, просто интегрировал Eloquent в мою собственную платформу). Я использовал преобразование метод перебора коллекции и unserialize
один из столбцов каждой записи, затем развалился коллекция для размещения всех несериализованных объектов в одном массиве.
Вот логика:
$orders = Order::where('user', $user)->orderBy('id', 'desc')->get();
$orders->transform(function($order, $key) {
$order->cart = unserialize($order->cart);
$items = $order->cart->items;
return $items;
});
$collapsed = $orders->collapse();
И вывод:
[
{
"qty": "2",
"price": 200,
"item": {
"id": 1,
"title": "Black Hoodie",
"img": "https://s3.amazonaws.com/bucket/black-hoodie.jpg",
"description": "Plain Black Hoodie.",
"price": 100
}
},
{
"qty": "2",
"price": 200,
"item": {
"id": 2,
"title": "Green Hoodie",
"img": "https://s3.amazonaws.com/bucket/green-hoodie.jpg",
"description": "Plain Green Hoodie.",
"price": 100
}
},
{
"qty": 1,
"price": 100,
"item": {
"id": 2,
"title": "Green Hoodie",
"img": "https://s3.amazonaws.com/bucket/green-hoodie.jpg",
"description": "Plain Green Hoodie.",
"price": 100
}
},
{
"qty": 1,
"price": 100,
"item": {
"id": 1,
"title": "Black Hoodie",
"img": "https://s3.amazonaws.com/bucket/black-hoodie.jpg",
"description": "Plain Black Hoodie.",
"price": 100
}
}
]
Теперь, что я хочу сделать дальше, это объединить все идентичные объекты в этом массиве, в идеале их "item":{"id"}
значение, в один объект — добавление их qty
а также price
свойства вместе, оставляя item
свойство то же самое.
Мой желаемый результат будет
[
{
"qty": "3",
"price": 300,
"item": {
"id": 1,
"title": "Black Hoodie",
"img": "https://s3.amazonaws.com/bucket/black-hoodie.jpg",
"description": "Plain Black Hoodie.",
"price": 100
}
},
{
"qty": "3",
"price": 300,
"item": {
"id": 2,
"title": "Green Hoodie",
"img": "https://s3.amazonaws.com/bucket/green-hoodie.jpg",
"description": "Plain Green Hoodie.",
"price": 100
}
}
]
Красноречивый ТОНН Из замечательных методов, доступных для работы с коллекциями, я просто застрял в правильной комбинации для эффективного достижения того, что я хочу сделать.
Попробуй это:
use Illuminate\Support\Fluent;
use Illuminate\Support\Collection;
// Mocking data to meet your requirements.
// Wrapping attributes inside fluent object,
// so we'll have almost same object like Eloquent model
$orders = new Collection([
new Fluent([
'qty' => 2,
'price' => 200,
'item' => new Fluent([
'id' => 1,
'price' => 100,
'title' => 'Black Hoodie',
'img' => 'https://s3.amazonaws.com/bucket/black-hoodie.jpg',
'description' => 'Plain Black Hoodie.',
])
]),
new Fluent([
'qty' => 2,
'price' => 200,
'item' => new Fluent([
'id' => 2,
'price' => 100,
'title' => 'Green Hoodie',
'img' => 'https://s3.amazonaws.com/bucket/green-hoodie.jpg',
'description' => 'Plain Green Hoodie.',
])
]),
new Fluent([
'qty' => 1,
'price' => 100,
'item' => new Fluent([
'id' => 2,
'price' => 100,
'title' => 'Green Hoodie',
'img' => 'https://s3.amazonaws.com/bucket/green-hoodie.jpg',
'description' => 'Plain Green Hoodie.',
])
]),
new Fluent([
'qty' => 1,
'price' => 100,
'item' => new Fluent([
'id' => 1,
'price' => 100,
'title' => 'Black Hoodie',
'img' => 'https://s3.amazonaws.com/bucket/black-hoodie.jpg',
'description' => 'Plain Black Hoodie.',
])
])
]);
// Here's something you might interested
$result = $orders->groupBy('item.id')
->map(function ($orders, $itemId) {
return new Fluent([
'qty' => $orders->sum('qty'), // calculating quantity
'price' => $orders->sum('price'), // calculating total price
'item' => $orders->first()->item // leave the item as it is
]);
});
// You may evaluate the result here
dd($result);
Более «сырой» пример:
use Illuminate\Support\Collection;
$orderOne = [
'id' => 1,
'price' => 100,
'title' => 'Black Hoodie',
'img' => 'https://s3.amazonaws.com/bucket/black-hoodie.jpg',
'description' => 'Plain Black Hoodie.',
];
$orderTwo = [
'id' => 2,
'price' => 100,
'title' => 'Green Hoodie',
'img' => 'https://s3.amazonaws.com/bucket/green-hoodie.jpg',
'description' => 'Plain Green Hoodie.',
];
$orders = new Collection([
[
'qty' => 2,
'price' => 200,
'item' => $orderOne
],
[
'qty' => 2,
'price' => 200,
'item' => $orderTwo
],
[
'qty' => 1,
'price' => 100,
'item' => $orderTwo
],
[
'qty' => 1,
'price' => 100,
'item' => $orderOne
]
]);
$result = $orders->groupBy('item.id')
->map(function ($orders, $itemId) {
return [
'qty' => $orders->sum('qty'),
'price' => $orders->sum('price'),
'item' => $orders->first()['item']
];
});
dd($result);
Других решений пока нет …