Выпуск коллекции Laravel
После долгих поисков и поиска в стеке, я решил, что мне нужна ваша помощь.
Я должен получить количество поставок для каждой поставки определенным поставщиком. Я знаю, это звучит странно, но позвольте мне объяснить:
У меня есть модель Поставщика, у которой много поставок, и у каждой поставки есть много запасов, у которых есть количество. Так что теперь я строю представление, в котором я хочу представить каждое предложение с их количеством по определенному поставщику.
Вот что я придумал в своем контроллере:
foreach ($suppliers as $supplier) {
foreach($supplier->supplies as $supply){
if(!$comp_supplies->contains('name', $supply->name)){
$comp_supplies->push(['name'=>$supply->name, 'supplier'=>[['name'=> $supplier->name, 'quantity' => $supply->stocks->first()->quantity]]]);
}elseif($comp_supplies->contains('name', $supply->name)){
$array = (['name'=> $supplier->name, 'quantity' => $supply->stocks->first()->quantity]);
$array2 = $comp_supplies->where('name', $supply->name)->first()['supplier'];
array_push($array2, $array);
//dd($array2);
$comp_supplies->where('name', $supply->name)->first()['supplier'] = $array2;
dd($comp_supplies->where('name', $supply->name)->first()['supplier']);
}
}
}
Поэтому я перебираю своих поставщиков и снова перебираю поставки от каждого из них. Теперь я хочу заполнить коллекцию, которую я хочу в результате.
Если в этой коллекции нет источника с именем "$supply->name", я помещаю массив с именем источника и создаю массив "поставщики", в котором я также устанавливаю первую запись с информацией о текущем поставщике.
Теперь мы приближаемся к моей проблеме.
Если comp_supply уже содержит поставку с текущим именем поставки, если нужно вставить нового поставщика в уже существующий массив "поставщик", который мы создали в первом "если".
Поэтому я создал $ массив, который содержит новую информацию о поставщике, и $array2, который содержит массив поставщиков ($comp_supplies->where('name', $supply->name)->first()['supplier']) мы уже сделали.
Теперь, если я вставлю $ array в $ array2 и dd(array2), все будет работать так, как я хочу. Но если я сейчас установлю
$comp_supplies->where('name', $supply->name)->first()['supplier'] = $array2
а потом
dd($comp_supplies->where('name', $supply->name)->first()['supplier']);
это не изменилось.
Я застрял в этой проблеме на 2 часа и очень расстроился.
Пожалуйста, если у кого-то есть идея, что я могу сделать, чтобы решить эту проблему, или если я знаю, где я могу искать дальше, дайте мне знать
Вот также миграции:
Поставщик:
public function up()
{
Schema::create('suppliers', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->unsignedInteger('coordinates_id')->index()->nullable();
$table->timestamps();
});
}
Расходные материалы:
public function up()
{
Schema::create('supplies', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->unsignedInteger('supplier_id');
$table->foreign('supplier_id')
->references('id')
->on('suppliers')
->onDelete('cascade');
$table->timestamps();
});
}
Запасы:
public function up()
{
Schema::create('stocks', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('supplies_id');
$table->foreign('supplies_id')
->references('id')
->on('supplies')
->onDelete('cascade');
$table->integer('quantity');
$table->timestamps();
});
}
3 ответа
Ваша проблема связана с тем, как PHP работает с массивами. Массивы передаются по значению, а не по ссылке, поэтому при вызове $comp_supplies->where('name', $supply->name)->first()
вы на самом деле получаете копию массива, и, следовательно, изменяя значение в индексе 'supplier'
изменяет только значение копии, а не значение исходного массива.
Вы можете проверить это поведение с помощью этого примера кода:
class TestList
{
protected $values;
public function push($value)
{
$this->values[] = $value;
}
public function get($index)
{
return $this->values[$index];
}
}
$list = new TestList();
$list->push(['test' => 1]);
var_dump($list->get(0)['test']); // int(1)
$list->get(0)['test'] = 2;
var_dump($list->get(0)['test']); // still int(1)...
Вы можете решить эту проблему, используя объекты вместо массивов, потому что объекты передаются по ссылке (обратите внимание на (object)
бросать):
$list = new TestList();
$list->push((object)['test' => 1]);
var_dump($list->get(0)->test); // int(1)
$list->get(0)->test = 2;
var_dump($list->get(0)->test); // int(2)!
Вместо
$comp_supplies->where('name', $supply->name)->first()['supplier'] = $array2;
Вы должны использовать:
$key = $comp_supplies->where('name', $supply->name)->get()->keys()->first();
$comp_supplies[$key]['supplier'] = $array2;
потому что вы вставляете в массивы коллекций, поэтому сначала вам нужно найти действительный ключ коллекции, чтобы позже вы могли обновить этот массив для этого ключа
Попробуй это
$comp_supplies->where('name', $supply->name)->first()->update($array2)
Вместо
$comp_supplies->where('name', $supply->name)->first()['supplier'] = $array2