Reputation: 13
Need to merge two collections
I have two collections and need to merge them in one collection
these collections was output of two queries using Eloquent
The First Result is like below:
Collection {#350
#items: array:2 [
0 => {#342
+"id": 1
+"code": "C000215"
+"name": "Mostafa Mohamed Bayomi"
+"mobile1": "01228902157"
+"mobile2": ""
+"CoachServiceCount": 0
+"CourseServiceCount": 1
+"CommunicationCount": 0
}
1 => {#337
+"id": 2
+"code": "C000216"
+"name": "Sayed Mohamed Bayomi"
+"mobile1": "01228902158"
+"mobile2": ""
+"CoachServiceCount": 0
+"CourseServiceCount": 2
+"CommunicationCount": 0
}
]
}
The second query result is like below:
Collection {#350
#items: array:2 [
0 => {#346
+"id": 1
+"code": "C000215"
+"name": "Mostafa Mohamed Bayomi"
+"mobile1": "01228902157"
+"mobile2": ""
+"CoachServiceAmount": 0.0
}
1 => {#340
+"id": 2
+"code": "C000216"
+"name": "Sayed Mohamed Bayomi"
+"mobile1": "01228902158"
+"mobile2": ""
+"CoachServiceAmount": 0.0
}
]
}
I used this code to merge both collections
$combined = $firstCollection->merge($secondCollection)
I expected below output
Collection {#350
#items: array:2 [
0 => {#346
+"id": 1
+"code": "C000215"
+"name": "Mostafa Mohamed Bayomi"
+"mobile1": "01228902157"
+"mobile2": ""
+"CoachServiceCount": 0
+"CourseServiceCount": 1
+"CommunicationCount": 0
+"CoachServiceAmount": 0.0
}
1 => {#340
+"id": 2
+"code": "C000216"
+"name": "Sayed Mohamed Bayomi"
+"mobile1": "01228902158"
+"mobile2": ""
+"CoachServiceCount": 0
+"CourseServiceCount": 2
+"CommunicationCount": 0
+"CoachServiceAmount": 0.0
}
]
}
But I got this output
Collection {#350
#items: array:4 [
0 => {#342
+"id": 1
+"code": "C000215"
+"name": "Mostafa Mohamed Bayomi"
+"mobile1": "01228902157"
+"mobile2": ""
+"CoachServiceCount": 0
+"CourseServiceCount": 1
+"CommunicationCount": 0
}
1 => {#337
+"id": 2
+"code": "C000216"
+"name": "Sayed Mohamed Bayomi"
+"mobile1": "01228902158"
+"mobile2": ""
+"CoachServiceCount": 0
+"CourseServiceCount": 2
+"CommunicationCount": 0
}
2 => {#346
+"id": 1
+"code": "C000215"
+"name": "Mostafa Mohamed Bayomi"
+"mobile1": "01228902157"
+"mobile2": ""
+"CoachServiceAmount": 0.0
}
3 => {#340
+"id": 2
+"code": "C000216"
+"name": "Sayed Mohamed Bayomi"
+"mobile1": "01228902158"
+"mobile2": ""
+"CoachServiceAmount": 0.0
}
]
}
Upvotes: 0
Views: 1230
Reputation: 1332
Use the union
method: https://laravel.com/docs/10.x/collections#method-union
The union method adds the given array to the collection. If the given array contains keys that are already in the original collection, the original collection's values will be preferred:
$collection = collect([1 => ['a'], 2 => ['b']]);
$union = $collection->union([3 => ['c'], 1 => ['d']]);
$union->all();
// [1 => ['a'], 2 => ['b'], 3 => ['c']]
Upvotes: 0
Reputation: 3835
The documentation for merge() contains the following text:
The merge method merges the given array or collection with the original collection. If a string key in the given items matches a string key in the original collection, the given items's value will overwrite the value in the original collection (...) If the given items's keys are numeric, the values will be appended to the end of the collection
Meaning merge()
will not work as you'd expected, since you are using numeric keys.
One solution for your issue would be to use non-numeric values as array keys, this solution will only work if the chosen field (code
in the example, is the primary key):
$firstCollection = $firstCollection->keyBy('code');
$secondCollection = $secondCollection->keyBy('code');
$combined = $firstCollection->merge($secondCollection);
// Optional: reset the array keys to be numeric
$combined = $combined->values();
The keyBy method keys the collection by the given key. If multiple items have the same key, only the last one will appear in the new collection (source)
The values method returns a new collection with the keys reset to consecutive integers (source)
If you have the same amount of elements and in the same order in both collections, you could do this:
$combined = $firstCollection->zip($secondCollection);
The zip method merges together the values of the given array with the values of the original collection at the corresponding index (source)
Upvotes: 2