Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel merge collections failing?

I'm trying to merge several collections but I'm not able to do this for any reason. My code looks like that:

$restaurant = \App\Restaurant::find(3);
$images     = $restaurant->images;
$userimages = $restaurant->userimages;
$hours      = $restaurant->hours;

$collectionMerge1 = $images->merge($userimages)->merge($hours);
$collectionMerge2 = $restaurant->userimages->merge($hours)->merge($images);
$collectionMerge3 = collect(array_merge($images->all(), $userimages->all(), $hours->all()));

The only merge that works is the last one. The previous ones are not showing all items that the collections contains. Why is this? What am I doing wrong? If you take a look to the picture you will see that there are missing objects in merges 1 and 2. I've tried several ways to do that, but only works the last one. Maybe the merge method is having issues with keys?

enter image description here

like image 857
bigbiggerpepe Avatar asked Feb 05 '23 07:02

bigbiggerpepe


2 Answers

In general i feel there is a lot of pitfalls with merge, i believe that most of the problems arises when you tries to merge key value arrays together or concat indexed arrays by using merge().

The solution for this problem, is to use concat instead of using the merge() approach.. Concat adds another collection or array to the end of the current collection. So you will not get conflicts when used on indexed arrays.

Simply use the Laravel collection approach as shown here.

$images = $images->concat($userimages)->concat($hours);
like image 88
mrhn Avatar answered Feb 08 '23 16:02

mrhn


This is old, but for posterity.

Let me give you simple example - easier to understand, than your collections.

It will be applied to yours at the bottom.

What you describe happens when initial Eloquent collection: $cars - has same id key as one of the following collections.

e.g. $cars has same id as element from $bikes

If you use it like this:

$vehicles = $cars->merge($bikes);

… you will get overwrite.

You get same overwrite, when you use it in this fashion as well:

$vehicles = $cars->merge($buses)->merge($bikes);

Regardless, where you put bikes when merging.

There is a simple workaround:

$vehicles = collect();
$vehicles = $vehicles->merge($buses)->merge($bikes)->merge($cars);

In this case, since your initial collection has no elements, it cannot conflict with any following collection and you get no overwrites.

It should work in any merging order, as long as empty collection comes first.

In your example, instead of:

$collectionMerge1 = $images->merge($userimages)->merge($hours);

You should do something like this:

$collectionMerge1 = collect();
$collectionMerge1 = $collectionMerge1->merge($images)->merge($userimages)->merge($hours);

Since empty collection is a base collection for merging, it does not mess with any following collection as it has no elements.

like image 36
Jeffz Avatar answered Feb 08 '23 15:02

Jeffz