Jak połączyć dwa php Doctrine 2 ArrayCollection ()

82

Czy jest jakaś wygodna metoda, która pozwala mi połączyć dwie doktryny ArrayCollection()? coś jak:

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

Chcę tylko wiedzieć, czy mogę zaoszczędzić sobie na iterowaniu drugiej kolekcji i dodawaniu każdego elementu jeden po drugim do pierwszej kolekcji.

Dzięki!

Throoze
źródło
3
+1, ponieważ jest to powszechna i potrzebna metoda
JavierIEH

Odpowiedzi:

171

Dla mnie lepszy (i działający) wariant:

$collection3 = new ArrayCollection(
    array_merge($collection1->toArray(), $collection2->toArray())
);
pliashkou
źródło
Bez wątpienia najlepsza odpowiedź.
Carles
Polecam to rozwiązanie
ioleo
Próbuję zrobić to samo, ale w tablicy: array_merge ($ scaled_arr, $ doct_collection-> toArray ()); ale nie otrzymuję błędu lub działa ($ scaled_arr jest pusty). Jakieś pomysły?
Guy
5
Może $ scaled_arr = array_merge ($ scaled_arr, $ doct_collection-> toArray ())?
pliashkou
12

Możesz po prostu zrobić:

$a = new ArrayCollection();
$b = new ArrayCollection();
...
$c = new ArrayCollection(array_merge((array) $a, (array) $b));
Daniel Ribeiro
źródło
6
Nie rozumiem, dlaczego jest to tak dużo głosów za. To jest po prostu złe. Rzutowanie obiektu na tablicę nie wywołuje toArray(). Zobacz, co się stanie
greg0ire
21
Podczas gdy mentalność mafii jest zawsze fajna, czy ktokolwiek z was próbował tego przed odrzuceniem? ArrayCollection implementuje IteratorAggregate, który umożliwia rzutowanie kolekcji jako tablicy i będzie działać zgodnie z oczekiwaniami.
Lewis,
5
Dzięki Bogu, ktoś mądry!
Daniel Ribeiro,
1
@Lewis: Wcześniej było to uzależnione, nie działało dla mnie (nie miałem czasu, żeby się w to zagłębić). Dlatego musiałem napisać inny wariant
pliashkou
2
@Lewis: trochę spóźniony na imprezę, ale wracam do tego problemu i tak próbowałem i nie, to nie działa, stąd głos negatywny.
greg0ire
10

Jeśli musisz zapobiegać duplikatom, ten fragment może pomóc. Używa wariadycznego parametru funkcji do użycia z 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;
}

Może się przydać w niektórych przypadkach.

Matthias Brock
źródło
1
Lub użyj$collection3 = new ArrayCollection(array_unique(array_merge($collection1->toArray(), $collection2->toArray())));
spdionis
Tak, ale ta i inna popularna odpowiedź, która robi to samo, konwertuje cały obiekt modelu na tablice, co ogranicza dalszą funkcjonalność.
zera i jedynki
3
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray()); 

To powinno być szybsze niż array_merge. Zduplikowane nazwy kluczy z $collection1są zachowywane, gdy ta sama nazwa klucza jest obecna w $collection2. Bez względu na rzeczywistą wartość

kanariezwart
źródło
toArray()zwraca tablicę, na arraypewno nie musisz wpisywać innej wskazówki ?
Jimbo
@jimbo: masz rację, ale jeśli z jakiegoś powodu pierwszy $collection->toArray()wraca nulllub false. Kończy się fatalnym błędem.
kanariezwart
Słuszna uwaga - chociaż jeśli Doctrine nie powiedzie się podczas konwersji na tablicę, to coś jest nie tak z bazą kodu Doctrine;)
Jimbo
2

Nadal musisz iterować kolekcje, aby dodać zawartość jednej tablicy do drugiej. Ponieważ ArrayCollection jest klasą opakowującą, możesz spróbować scalić tablice elementów przy jednoczesnym zachowaniu kluczy, klucze tablic w $ collection2 przesłaniają wszelkie istniejące klucze w $ collection1 przy użyciu funkcji pomocniczej poniżej:

$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
źródło
Do czego służy &operator? czy to jest jak w C? Cóż, oczywiście jest to rozwiązanie, ale zachowanie, którego się spodziewałem, polegało na tym, że miałbym mieć ArrayCollectionjuż jakieś wartości i użyć metody ( ArrayCollectionjeśli istnieje, lub izolowanej procedury, takiej jak twoja), aby dodać wartości innej istniejącej ArrayCollection. Twoje rozwiązanie wymaga stworzenia nowego ArrayCollection, co utrudnia proces. W każdym razie dzięki!
Throoze
& Jest przejściem przez referencję, ponieważ nie chcesz zmieniać argumentów. Zamiast tego można przepisać metodę, aby iterować po kolekcjach. Ta metoda nie ma argumentów, więc możesz łączyć dowolną liczbę kolekcji.
Stephen Senkomago Musoke
Chodzi o to, że moje zbiory źródłowe
pobieram
Chodziło mi o to, że możesz napisać metodę mergeCollections ($ collection1, $ collection2), która łączy zawartość $ collection2 w $ collection1, możesz ponownie użyć funkcji mergeCollection w innym miejscu w swojej aplikacji
Stephen Senkomago Musoke
Zamiast tego powinieneś użyć array_merge ().
Daniel Ribeiro,
0

Dodaj kolekcję do tablicy, na podstawie komentarza Yury Pliashkou (wiem, że nie odpowiada on bezpośrednio na pierwotne pytanie, ale na to już udzielono odpowiedzi, a to może pomóc innym wylądować tutaj):

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

Może ci się podoba ... może nie ... Pomyślałem o wyrzuceniu tego na wypadek, gdyby ktoś tego potrzebował.

Manatax
źródło
Zawsze dobrze jest mieć jakąś różnorodność możliwych rozwiązań. Ale w porównaniu z innymi nie widzę korzyści z używania twojego rozwiązania. Czy mógłbyś opisać to trochę bardziej szczegółowo?
k00ni
1
Wylądowałem na tym pytaniu, gdy musiałem dodać kolekcję do tablicy, jak niektórzy inni, ale mój przypadek użycia wymagał sprawdzenia pustej tablicy / kolekcji, więc udostępniłem ją tutaj.
Manatax
0

Uwaga! Unikaj dużego zagnieżdżania elementów rekurencyjnych. array_unique - ma rekurencyjny limit osadzania i powoduje, żePHP 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);
Валентин Анохин
źródło
-1

Korzystanie z 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
źródło
Mała wskazówka : część echo $a.toArray();z pewnością zgłosi błąd, ponieważ toArraynie jest prawidłową funkcją. Musi być przynajmniej echo $a->toArray();. Ponadto wynik końcowy powinien być sformatowany jako kod.
k00ni