2012-04-10 5 views
66

Gibt es eine bequeme Methode, die es mir erlaubt, zwei Doctrine ArrayCollection() zu verketten? so etwas wie:Wie füge ich zwei 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 } 

Ich will nur wissen, ob ich mich über die zweite Kollektion iterieren speichern kann und das Hinzufügen jedes Element einzeln zu der ersten Kollektion.

Danke!

+3

+1, weil seine eine gemeinsame und benötigt Methode – JavierIEH

Antwort

129

besser (und arbeiten) Variante für mich:

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

Beste Antwort, kein Zweifel. – carles

+0

Ich empfehle diese Lösung – loostro

+0

Ich versuche, das gleiche aber in ein Array zu tun: array_merge ($ merged_arr, $ doct_collection-> toArray()); aber bekomme entweder keinen Fehler oder funktioniert es ($ merged_arr ist leer). Irgendwelche Ideen? – Guy

1

Sie müssen immer noch über die Sammlungen iterieren, um den Inhalt eines Arrays zu einem anderen hinzuzufügen. Da die Arraycollection eine Wrapper-Klasse ist, könnten Sie versuchen, die Arrays von Elementen verschmelzen, während der Schlüssel beibehalten, Collection2 der Array-Schlüssel in $ überschreibt alle vorhandenen Schlüssel in $ collection1 eine Hilfsfunktion unter Verwendung von:

$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

Was ist das '' & Operator? ist es so etwas wie in C? Nun, natürlich ist das eine Lösung, aber das erwartete Verhalten war eine 'ArrayCollection', die bereits einige Werte enthielt und eine Methode (von' ArrayCollection', falls es existiert, oder eine isolierte Prozedur, wie Ihre) zu verwenden füge die Werte einer anderen vorhandenen 'ArrayCollection' hinzu. Ihre Lösung erfordert das Erstellen einer neuen 'ArrayCollection', die den Prozess stark macht. Danke trotzdem! – Throoze

+0

Das & ist ein Pass als Referenz, da Sie die Argumente nicht ändern möchten. Sie könnten die Methode neu schreiben, um stattdessen über die Sammlungen zu iterieren. Für diese Methode gibt es keine Argumente, sodass Sie beliebig viele Sammlungen kombinieren können. –

+0

Die Sache ist, ich bekomme meine Quellensammlungen dynamisch, so kann ich den Anruf nicht so machen, wie Sie vorschlagen ... – Throoze

13

Sie können einfach tun:

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

Ich verstehe nicht, warum dies so viele upvotes bekommt. Es ist einfach falsch. Wenn Sie ein Objekt an ein Array übergeben, wird 'toArray()' nicht aufgerufen. [Siehe, was passiert] (http://www.php.net/manual/en/language.types.array.php#language.types.array.casting) – greg0ire

+0

Das funktioniert nicht –

+16

Während Mob-Mentalität immer Spaß macht, Hat jemand von euch das tatsächlich versucht, bevor er es abgesagt hat? ArrayCollection implementiert IteratorAggregate, mit dem Sie die Sammlung als Array umwandeln können, und sie funktioniert wie erwartet. – Lewis

1

Basierend auf Yury Pliashkou ‚s Kommentar:

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

Vielleicht magst du es ... vielleicht nicht ... Ich dachte nur daran, es rauszuschmeißen, nur für den Fall, dass jemand es braucht.

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

Dies sollte schneller sein als array_merge. Doppelte Schlüsselnamen von $collection1 werden beibehalten, wenn der gleiche Schlüsselname in $collection2 vorhanden ist. Egal, was der tatsächliche Wert ist

+0

'toArray()' gibt ein Array zurück, du solltest nicht unbedingt in ein anderes 'Array' schreiben? – Jimbo

+0

@jimbo: Sie haben recht, aber wenn aus irgendeinem Grund die erste '$ collection-> toArray()' 'null' oder' false' zurückgibt. Sie haben einen schwerwiegenden Fehler. – kanariezwart

+0

Fairer Punkt - obwohl Doctrine nicht in ein Array konvertieren kann, stimmt etwas mit der Doctrine Codebase nicht. – Jimbo

7

Wenn Sie erforderlich sind, um Dubletten zu verhindern, kann dieses Snippet helfen. Es verwendet einen variadischen Funktionsparameter zur Verwendung mit 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; 
} 

Kann in einigen Fällen handlich sein.

0

Mit 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