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!


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())
);

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

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.


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


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

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.


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

-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

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.