#php #laravel #eloquent #query-builder #laravel-query-builder
#php #laravel #eloquent #конструктор запросов #laravel-конструктор запросов
Вопрос:
У меня есть таблица движения запасов, которая показывает историю продукта (получение, перемещение местоположения и т. Д.)
У меня есть два запроса, которые вычисляют (через совокупные суммы):
- Исходное полученное кол-во.
- Текущее текущее количество (после того, как вещи были перемещены).
Оба этих запроса возвращают коллекцию одинаковых моделей. В каждом из них всегда будет одинаковое количество результатов, а идентификаторы product_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 в массив, поскольку мне нужны отношения, которые встроены в него.
В настоящее время я взломал это следующим образом:
$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
Функция рекурсивно преобразует массив обратно в объект, поэтому я могу использовать селектор стрелок так же, как когда это была его исходная коллекция, но я уверен, что должен быть лучший способ!
Я пробовал:
- Слияние
- Объединение
- Все
Моя конечная цель — иметь возможность использовать полученную коллекцию следующим образом:
@foreach($stockMovements as $stockMovement)
{{ $stockMovement->id }}
{{ $stockMovement->live_qty }}
{{ $stockMovement->received_qty }}
@endforeach
Комментарии:
1. «Все наборы с несколькими результатами, возвращаемые Eloquent, являются экземплярами объекта Illuminate Database Eloquent Collection». Почему вы сказали «не коллекции»?
2. Я предполагаю, что я думаю о коллекции как о «коллекции результатов модели eloquent». Я хочу убедиться, что я не разбиваю модель stockMovement на массив или обычную коллекцию, т.Е. Я хочу сохранить все ее функциональные возможности, например,
$stockMovement->product->title
где stockMovement принадлежит продукту, через product_id3. Я думаю, вы можете попробовать использовать этот способ: laravel.com/docs/5.8/eloquent-relationships
4. @loic.lopez спасибо. Я уже знаю, что такое отношения. Я просто пытаюсь объединить два вышеуказанных запроса, сохраняя при этом отношения нетронутыми. Если я преобразую в массив перед слиянием, то отношения будут потеряны.
Ответ №1:
Вы можете использовать этот код:
$collection = collect();
$cars = Car::all();
$bikes = Bike::all();
foreach ($cars as $car)
$collection->push($car);
foreach ($bikes as $bike)
$collection->push($bike);
Ответ №2:
Я знаю, что вы упомянули в своем вопросе, что вы не имели в виду коллекции, а также что вы уже пытались объединить, но ради обсуждения я подумал, что добавлю свой ответ, поскольку это сработало именно для того, что мне было нужно; объединение ответов двух вызовов модели.
$quote = AppAllQuotes::withoutGlobalScopes()->find($quote_id);
$settings = AppSettings::findOrFail(1);
$settings = collect($settings);
$quote = collect($quote);
$merged = $quote->merge($settings);
return $merged;
Вы должны сначала инкапсулировать ответы модели в виде коллекций с collect
помощью помощника, затем вы можете объединить их вместе. Затем вывод обрабатывается как логическое объединение, сохраняя данные из обеих моделей в единственном выходе.
Ответ №3:
Вы могли бы сделать что-то вроде этого:
$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;
});