How to properly merge multiple collections in Laravel
Solution 1
What I ended up doing was separating each step. It was the merge chaining that was killing it, because some or all of the collections could have been invalid.
$allItems = new \Illuminate\Database\Eloquent\Collection; //Create empty collection which we know has the merge() method
$allItems = $allItems->merge($collection1);
$allItems = $allItems->merge($collection2);
$allItems = $allItems->merge($collection3);
$allItems = $allItems->merge($collection4);
Solution 2
I had the same question, so I solved it in the following way:
$clients = ClientAccount::query()->get();
$admins = AdminAccount::query()->get();
$users = collect($clients)->merge($admins)->merge($anotherCollection)->merge(...);
Solution 3
I used ->merge()
but faced a small issue. So I'm adding this in case anyone else face the same issue. ->concat()
is a better solution on database collection merging.
$allItems = new \Illuminate\Database\Eloquent\Collection;
$allItems = $allItems->concat($collection1);
$allItems = $allItems->concat($collection2);
The reason for this is when merging they take ID of the table as the key. So if two tables have two records with same table id ->merge()
will add only one record to $allItems
. But ->concat()
will add two records as they should.
Solution 4
depend on your data, if collection is actually null or your php support it you can do:
$allItems = $collection1->merge($collection2 ?: collect())
->merge($collection3 ?: collect())
->merge($collection4 ?: collect())
->merge($collection5 ?: collect());
or you want to do a reduce:
$allItems = collect([$collection2, $collection3, $collection4])->reduce(function($arr, $item) {
if (empty($item) || $item->isEmpty())
return $arr;
return $arr->merge($item);
}, $collection1);
or plain php reduce without overhead
$allItems = array_reduce([
$collection2,
$collection3,
$collection4
], function($arr, $item) {
if (empty($item) || $item->isEmpty())
return $arr;
return $arr->merge($item);
}, $collection1);
Marcel Gruber
C#.NET VB.NET Sitecore SEO PHP / Laravel Knockout.JS Objective C Owner of Luxica Consulting Corp.
Updated on November 19, 2021Comments
-
Marcel Gruber over 2 years
I want to merge multiple collections into one. I do have a solution, which is the following:
$allItems = $collection1->merge($collection2) ->merge($collection3) ->merge($collection4) ->merge($collection5);
This actually does work, but I run into problems in cases where some or all of the collections contain no objects. I get an error along the lines of
call to merge() on non object
.I actually tried to create an array of all of the collections, and then iterate through them, while checking their validity, but it didn't work and I feel it wasn't very elegant.
How can I elegantly iterate through this process of merging multiple collections, while taking into account that some or all of the collections might be empty or invalid? Appreciated!