How to merge two php Doctrine 2 ArrayCollection()
PhpSymfonyDoctrine OrmArraycollectionPhp Problem Overview
Is there any convenience method that allows me to concatenate two Doctrine ArrayCollection()
? something like:
$collection1 = new ArrayCollection();
$collection2 = new ArrayCollection();
$collection1->add($obj1);
$collection1->add($obj2);
$collection1->add($obj3);
$collection2->add($obj4);
$collection2->add($obj5);
$collection2->add($obj6);
$collection1->concat($collection2);
// $collection1 now contains {$obj1, $obj2, $obj3, $obj4, $obj5, $obj6 }
I just want to know if I can save me iterating over the 2nd collection and adding each element one by one to the 1st collection.
Thanks!
Php Solutions
Solution 1 - Php
Better (and working) variant for me:
$collection3 = new ArrayCollection(
array_merge($collection1->toArray(), $collection2->toArray())
);
Solution 2 - Php
You can simply do:
$a = new ArrayCollection();
$b = new ArrayCollection();
...
$c = new ArrayCollection(array_merge((array) $a, (array) $b));
Solution 3 - Php
If you are required to prevent any duplicates, this snippet might help. It uses a variadic function parameter for usage with PHP5.6.
/**
* @param array... $arrayCollections
* @return ArrayCollection
*/
public function merge(...$arrayCollections)
{
$returnCollection = new ArrayCollection();
/**
* @var ArrayCollection $arrayCollection
*/
foreach ($arrayCollections as $arrayCollection) {
if ($returnCollection->count() === 0) {
$returnCollection = $arrayCollection;
} else {
$arrayCollection->map(function ($element) use (&$returnCollection) {
if (!$returnCollection->contains($element)) {
$returnCollection->add($element);
}
});
}
}
return $returnCollection;
}
Might be handy in some cases.
Solution 4 - Php
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray());
This should be faster than array_merge
. Duplicate key names from $collection1
are kept when same key name is present in $collection2
. No matter what the actual value is
Solution 5 - Php
You still need to iterate over the Collections to add the contents of one array to another. Since the ArrayCollection is a wrapper class, you could try merging the arrays of elements while maintaining the keys, the array keys in $collection2 override any existing keys in $collection1 using a helper function below:
$combined = new ArrayCollection(array_merge_maintain_keys($collection1->toArray(), $collection2->toArray()));
/**
* Merge the arrays passed to the function and keep the keys intact.
* If two keys overlap then it is the last added key that takes precedence.
*
* @return Array the merged array
*/
function array_merge_maintain_keys() {
$args = func_get_args();
$result = array();
foreach ( $args as &$array ) {
foreach ( $array as $key => &$value ) {
$result[$key] = $value;
}
}
return $result;
}
Solution 6 - Php
Add a Collection to an array, based on Yury Pliashkou's comment (I know it does not directly answer the original question, but that was already answered, and this could help others landing here):
function addCollectionToArray( $array , $collection ) {
$temp = $collection->toArray();
if ( count( $array ) > 0 ) {
if ( count( $temp ) > 0 ) {
$result = array_merge( $array , $temp );
} else {
$result = $array;
}
} else {
if ( count( $temp ) > 0 ) {
$result = $temp;
} else {
$result = array();
}
}
return $result;
}
Maybe you like it... maybe not... I just thought of throwing it out there just in case someone needs it.
Solution 7 - Php
Attention! Avoid large nesting of recursive elements. array_unique - has a recursive embedding limit and causes a PHP error Fatal error: Nesting level too deep - recursive dependency?
/**
* @param ArrayCollection[] $arrayCollections
*
* @return ArrayCollection
*/
function merge(...$arrayCollections) {
$listCollections = [];
foreach ($arrayCollections as $arrayCollection) {
$listCollections = array_merge($listCollections, $arrayCollection->toArray());
}
return new ArrayCollection(array_unique($listCollections, SORT_REGULAR));
}
// using
$a = new ArrayCollection([1,2,3,4,5,6]);
$b = new ArrayCollection([7,8]);
$c = new ArrayCollection([9,10]);
$result = merge($a, $b, $c);
Solution 8 - Php
Using Clousures PHP5 > 5.3.0
$a = ArrayCollection(array(1,2,3));
$b = ArrayCollection(array(4,5,6));
$b->forAll(function($key,$value) use ($a){ $a[]=$value;return true;});
echo $a.toArray();
array (size=6) 0 => int 1 1 => int 2 2 => int 3 3 => int 4 4 => int 5 5 => int 6