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!


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

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

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.


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ść


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

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ł.


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

-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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.