2012-04-10 5 views
66

Есть ли какой-либо удобный метод, который позволяет мне объединить две доктрины ArrayCollection()? что-то вроде:Как слить две php Doctrine 2 ArrayCollection()

$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 } 

Я просто хочу знать, если я могу спасти меня итерация 2 коллекции и добавляя каждый элемент по одному на 1-й коллекции.

Спасибо!

+3

+1 потому, что его общий и нужен метод – JavierIEH

ответ

129

Лучше (и работать) для меня вариант:

$collection3 = new ArrayCollection(
    array_merge($collection1->toArray(), $collection2->toArray()) 
); 
+0

Лучший ответ, без сомнения. – carles

+0

Я рекомендую это решение – loostro

+0

Я пытаюсь сделать то же самое, но в массив: array_merge ($ merged_arr, $ doct_collection-> toArray()); но я не получаю ни ошибки, ни работает ($ merged_arr пуст). Есть идеи? – Guy

1

Вам все равно нужно перебирать коллекции для добавления содержимого одного массива в другой. Поскольку ArrayCollection класс обертку, можно попробовать объединения массивов элементов, сохраняя при этом ключи, ключи массива в $ collection2 переопределить существующие ключи в $ collection1 с помощью вспомогательной функции ниже:

$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; 
} 
+0

Что '' & оператор? это что-то вроде в C? Ну, конечно, это решение, но я ожидал, что я должен был иметь «ArrayCollection», который уже содержал некоторые значения, и использовать метод («ArrayCollection», если он существует, или изолированную процедуру, такую ​​как ваша), чтобы добавьте значения другого существующего 'ArrayCollection'. Ваше решение требует создания нового 'ArrayCollection', что делает процесс тяжелым. Спасибо, в любом случае! – Throoze

+0

& is pass by reference, так как вы не хотите изменять аргументы. Вместо этого вы можете переписать метод для итерации над коллекциями. Для этого метода нет аргументов, поэтому вы можете объединить столько коллекций, сколько хотите. –

+0

Дело в том, что я получаю свои исходные коллекции динамически, поэтому я не могу сделать вызов так, как вы предлагаете ... – Throoze

13

Вы можете просто делать:

$a = new ArrayCollection(); 
$b = new ArrayCollection(); 
... 
$c = new ArrayCollection(array_merge((array) $a, (array) $b)); 
+5

Я не понимаю, почему у этого так много авотаций. Это просто неправильно. Отбрасывание объекта в массив не вызывает 'toArray()'. [Посмотрите, что произойдет] (http://www.php.net/manual/en/language.types.array.php#language.types.array.casting) – greg0ire

+0

Это не работает –

+16

Пока толпа менталитета всегда веселая, действительно ли кто-нибудь из вас попробовал это, прежде чем сбрасывать его? ArrayCollection реализует IteratorAggregate, который позволяет вам отображать коллекцию в виде массива, и она будет работать так же, как ожидалось. – Lewis

1

Основываясь на комментарий Yury Pliashkou «s:

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; 
} 

Возможно, вам это нравится ... может быть, нет ... Я просто подумал о том, чтобы выбросить его на случай, если кому-то это понадобится.

2
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray()); 

Это должно быть быстрее, чем array_merge. Повторяющиеся имена ключей от $collection1 сохраняются, когда такое же ключевое имя присутствует в $collection2. Независимо от того, что фактическое значение

+0

'toArray()' возвращает массив, вам не нужно указывать ключ другого массива? – Jimbo

+0

@jimbo: вы правы, но если по какой-либо причине первая '$ collection-> toArray()' возвращает 'null' или' false'. У вас закончилась фатальная ошибка. – kanariezwart

+0

Справедливая точка - хотя если Doctrine не удается преобразовать в массив, то что-то не так плохо с кодовой базой Doctrine;) – Jimbo

7

Если вам необходимо предотвратить любые дубликаты, этот фрагмент может помочь. Он использует параметр вариационной функции для использования с 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; 
} 

Может быть удобно в некоторых случаях.

0

Использование 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