Як об'єднати два php Doctrine 2 ArrayCollection ()


82

Чи існує якийсь зручний метод, який дозволяє поєднати дві доктрини ArrayCollection()? щось на зразок:

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

Я просто хочу знати, чи можу я заощадити ітерацію над другою колекцією та додавання кожного елемента по одному до 1-ї колекції.

Дякую!


3
+1, оскільки це загальноприйнятий і необхідний метод
JavierIEH

Відповіді:


171

Кращий (і робочий) варіант для мене:

$collection3 = new ArrayCollection(
    array_merge($collection1->toArray(), $collection2->toArray())
);

Найкраща відповідь, без сумніву.
Карлес

Я рекомендую це рішення
ioleo

Я намагаюся зробити те ж саме, але в масив: array_merge ($ merged_arr, $ doct_collection-> toArray ()); але я не отримую ні помилки, ні вона працює ($ merged_arr порожній). Будь-які ідеї?
Guy

5
Можливо $ merged_arr = array_merge ($ merged_arr, $ doct_collection-> toArray ())?
pliashkou

12

Ви можете просто зробити:

$a = new ArrayCollection();
$b = new ArrayCollection();
...
$c = new ArrayCollection(array_merge((array) $a, (array) $b));

6
Я не розумію, чому це набирає стільки голосів. Це просто неправильно. Передача об'єкта в масив не викликає toArray(). Подивіться, що станеться
greg0ire

21
Хоча менталітет натовпу завжди веселий, чи хтось із вас насправді пробував це, перш ніж проголосувати? ArrayCollection реалізує IteratorAggregate, що дозволяє передавати колекцію як масив, і вона працюватиме так, як очікувалося.
Льюїс

5
Слава Богу, хтось розумний!
Даніель Рібейро,

1
@ Льюїс: Раніше це викручувало, у мене це не спрацьовувало (я не мав часу в нього заходити). Тому мені довелося написати інший варіант
Пляшкоу

2
@ Льюїс: трохи пізно на вечірку, але я повертаюся до цієї проблеми, і так, я спробував, і ні, це не працює, отже, голос проти.
greg0ire

10

Якщо вам потрібно запобігти дублюванню, цей фрагмент може допомогти. Він використовує параметричний параметр функції для використання з 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;
}

У деяких випадках може бути корисним.


1
Або використайте$collection3 = new ArrayCollection(array_unique(array_merge($collection1->toArray(), $collection2->toArray())));
spdionis

Так, але ця та інша популярна відповідь, яка робить те саме, перетворює весь об’єкт моделі на масиви, що обмежує подальшу функціональність.
нулі і одиниці

3
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray()); 

Це має бути швидше ніж array_merge. Повторювані імена ключів від $collection1зберігаються, коли в них присутня однакова назва ключа $collection2. Незалежно від того, яке фактичне значення


toArray()повертає масив, вам не потрібно напевно вводити натяк на інший array?
Джимбо,

@jimbo: ти маєш рацію, але якщо з якоїсь причини перша $collection->toArray()повертається nullабо false. У вас трапляється фатальна помилка.
kanariezwart

Справедливий момент - хоча якщо Doctrine не перетворюється на масив, то щось не вдається з кодовою базою Doctrine;)
Джимбо

2

Вам все одно потрібно переглядати колекції, щоб додати вміст одного масиву до іншого. Оскільки ArrayCollection - це клас обгортки, ви можете спробувати об'єднати масиви елементів, зберігаючи ключі, ключі масиву в $ collection2 замінюють будь-які існуючі ключі в $ collection1, використовуючи допоміжну функцію нижче:

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

Для чого потрібен &оператор? це щось на зразок С? Ну, звичайно, це рішення, але поведінка, яку я очікував, мала мати такий, ArrayCollectionякий вже містив деякі значення, і використовувати метод ( ArrayCollectionякщо він існує, або ізольовану процедуру, подібну до вашої), щоб додати значення іншого існуючого ArrayCollection. Ваше рішення вимагає створення нового ArrayCollection, що ускладнює процес. Все одно, дякую!
Throoze

Значення & - це передача за посиланням, оскільки ви не хочете змінювати аргументи. Замість цього ви можете переписати метод для перебору колекцій. Для цього методу немає аргументів, тому ви можете об’єднати скільки завгодно колекцій.
Stephen Senkomago Musoke

Справа в тому, що я отримую свої вихідні колекції динамічно, тому я не можу здійснити дзвінок так, як ви пропонуєте ...
Throoze

Я мав на увазі, що ви можете написати метод mergeCollections ($ collection1, $ collection2), який об'єднує вміст $ collection2 у $ collection1, і ви можете повторно використовувати функцію mergeCollection в іншому місці, де знаходиться у вашому додатку
Стівен Сенкомаго Мусоке,

Натомість слід використовувати array_merge ().
Даніель Рібейро,

0

Додайте колекцію до масиву на основі коментаря Юрія Пляшкова (я знаю, що це не відповідає безпосередньо на вихідне запитання, але на це вже було дано відповідь, і це може допомогти іншим приземлитися тут):

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

Можливо, тобі це подобається ... може, ні ... Я просто думав викинути його туди на той випадок, якщо комусь це буде потрібно.


Завжди добре мати якесь різноманіття можливих рішень. Але в порівнянні з іншими, я не бачу користі у використанні вашого рішення. Не могли б ви описати це трохи детальніше?
k00ni

1
Я опинився на цьому питанні, коли потрібно було додати колекцію до масиву, як і деякі інші люди, але мій випадок використання вимагав перевірки порожнього масиву / колекції, тому я поділився ним тут.
Manatax

0

Увага! Уникайте великого вкладання рекурсивних елементів. array_unique - має рекурсивне обмеження на вбудовування та викликає 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

Використання 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

Невелика підказка : Частина echo $a.toArray();, безумовно, видасть помилку, оскільки toArrayне є допустимою функцією. Це повинно бути принаймні echo $a->toArray();. Крім того, результат у кінці повинен бути відформатований як код.
k00ni
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.