Wie man zwei PHP zusammenführt Doctrine 2 ArrayCollection ()

80

Gibt es eine bequeme Methode, mit der ich zwei Lehren verketten kann ArrayCollection()? etwas wie:

$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 möchte nur wissen, ob ich es mir ersparen kann, die 2. Sammlung zu durchlaufen und jedes Element einzeln zur 1. Sammlung hinzuzufügen.

Vielen Dank!

Throoze
quelle
3
+1, weil es eine übliche und notwendige Methode ist
JavierIEH

Antworten:

168

Bessere (und funktionierende) Variante für mich:

$collection3 = new ArrayCollection(
    array_merge($collection1->toArray(), $collection2->toArray())
);
Pliashkou
quelle
Ohne Zweifel die beste Antwort.
Carles
Ich empfehle diese Lösung
Ioleo
Ich versuche das gleiche zu tun, aber in ein Array: array_merge ($ fusioned_arr, $ doct_collection-> toArray ()); Ich erhalte aber weder einen Fehler noch funktioniert er ($ fusioned_arr ist leer). Irgendwelche Ideen?
Guy
5
Vielleicht $ fusioned_arr = array_merge ($ urged_arr, $ doct_collection-> toArray ())?
Pliashkou
12

Sie können einfach tun:

$a = new ArrayCollection();
$b = new ArrayCollection();
...
$c = new ArrayCollection(array_merge((array) $a, (array) $b));
Daniel Ribeiro
quelle
6
Ich verstehe nicht, warum dies so viele positive Stimmen bekommt. Es ist einfach falsch. Das Umwandeln eines Objekts in ein Array wird nicht aufgerufen toArray(). Sehen Sie, was passiert
greg0ire
21
Während Mob-Mentalität immer Spaß macht, hat jemand von euch dies tatsächlich versucht, bevor er es abgelehnt hat? ArrayCollection implementiert IteratorAggregate, mit dem Sie die Sammlung als Array umwandeln können und sie wie erwartet funktioniert.
Lewis
5
Gott sei Dank, jemand klug!
Daniel Ribeiro
1
@ Lewis: Es hat es vorher geredet, es hat bei mir nicht funktioniert (ich hatte keine Zeit, mich darauf einzulassen). Deshalb musste ich eine andere Variante schreiben
pliashkou
2
@ Lewis: ein bisschen spät zur Party, aber ich komme auf dieses Problem zurück, und ja, ich habe es versucht, und nein, es funktioniert nicht, daher die Ablehnung.
Greg0ire
10

Wenn Sie Duplikate verhindern müssen, kann dieses Snippet hilfreich sein. Für die Verwendung mit PHP5.6 wird ein variabler Funktionsparameter verwendet.

/**
 * @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;
}

Könnte in einigen Fällen nützlich sein.

Matthias Brock
quelle
1
Oder verwenden Sie$collection3 = new ArrayCollection(array_unique(array_merge($collection1->toArray(), $collection2->toArray())));
spdionis
Ja, aber diese und die andere beliebte Antwort, die dasselbe tut, konvertieren das gesamte Modellobjekt in Arrays, was die weitere Funktionalität einschränkt.
Nullen und Einsen
3
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray()); 

Dies sollte schneller sein als array_merge. Doppelte Schlüsselnamen von $collection1werden beibehalten, wenn derselbe Schlüsselname in vorhanden ist $collection2. Egal wie hoch der tatsächliche Wert ist

kanariezwart
quelle
toArray()Gibt ein Array zurück, sollten Sie arraysicher keinen anderen Tipp eingeben müssen ?
Jimbo
@jimbo: du hast recht, aber wenn aus irgendeinem grund der erste $collection->toArray()zurückkehrt nulloder false. Sie erhalten einen schwerwiegenden Fehler.
Kanariezwart
Fairer Punkt - obwohl, wenn Doctrine nicht in ein Array konvertiert werden kann, etwas mit der Doctrine-Codebasis nicht stimmt;)
Jimbo
2

Sie müssen die Sammlungen noch durchlaufen, um den Inhalt eines Arrays einem anderen hinzuzufügen. Da es sich bei der ArrayCollection um eine Wrapper-Klasse handelt, können Sie versuchen, die Arrays von Elementen unter Beibehaltung der Schlüssel zusammenzuführen. Die Array-Schlüssel in $ collection2 überschreiben alle vorhandenen Schlüssel in $ collection1 mithilfe einer der folgenden Hilfsfunktionen:

$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;
}
Stephen Senkomago Musoke
quelle
Wofür ist der &Betreiber? ist es so etwas wie in C? Nun, natürlich ist dies eine Lösung, aber das Verhalten, das ich erwartet hatte, bestand darin, eine zu haben, ArrayCollectiondie bereits einige Werte enthielt, und eine Methode (von ArrayCollection, falls vorhanden, oder eine isolierte Prozedur wie Ihre) zu verwenden, um die Werte einer anderen vorhandenen hinzuzufügen ArrayCollection. Ihre Lösung erfordert die Erstellung einer neuen ArrayCollection, was den Prozess schwer macht. Danke trotzdem!
Throoze
Das & ist eine Referenzübergabe, da Sie die Argumente nicht ändern möchten. Sie können die Methode neu schreiben, um stattdessen die Sammlungen zu durchlaufen. Es gibt keine Argumente für diese Methode, sodass Sie so viele Sammlungen kombinieren können, wie Sie möchten.
Stephen Senkomago Musoke
Die Sache ist, ich bekomme meine Quellensammlungen dynamisch, so dass ich den Anruf nicht so tätigen kann, wie Sie es vorschlagen ...
Throoze
Was ich damit gemeint habe ist, dass Sie eine Methode mergeCollections ($ collection1, $ collection2) schreiben können, die den Inhalt von $ collection2 in $ collection1 zusammenführt. Sie können die mergeCollection-Funktion an anderer Stelle wiederverwenden, wo in Ihrer Anwendung
Stephen Senkomago Musoke
Sie sollten stattdessen array_merge () verwenden.
Daniel Ribeiro
0

Fügen Sie einem Array eine Sammlung hinzu, basierend auf Yury Pliashkous Kommentar (ich weiß, dass die ursprüngliche Frage nicht direkt beantwortet wird, aber diese wurde bereits beantwortet, und dies könnte anderen helfen, hier zu landen):

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 gefällt es dir ... vielleicht auch nicht ... Ich habe nur daran gedacht, es rauszuwerfen, falls jemand es braucht.

Manatax
quelle
Es ist immer gut, eine Vielfalt an möglichen Lösungen zu haben. Aber im Vergleich zu den anderen sehe ich keinen Nutzen in der Verwendung Ihrer Lösung. Würde es Ihnen etwas ausmachen, es etwas detaillierter zu beschreiben?
k00ni
1
Ich bin auf diese Frage gestoßen, als ich wie einige andere Personen eine Sammlung zu einem Array hinzufügen musste, aber mein Anwendungsfall erforderte die Überprüfung auf leere Arrays / Sammlungen, sodass ich sie hier freigegeben habe.
Manatax
0

Beachtung! Vermeiden Sie große Verschachtelungen rekursiver Elemente. array_unique - hat eine rekursive Einbettungsgrenze und verursacht aPHP 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);
Валентин Анохин
quelle
-1

Verwenden von 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
Juja
quelle
Kleiner Hinweis : Das Teil echo $a.toArray();wird sicherlich einen Fehler auslösen, da toArrayes sich nicht um eine gültige Funktion handelt. Es muss mindestens sein echo $a->toArray();. Außerdem sollte die Ausgabe am Ende als Code formatiert sein.
k00ni