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.