Як об'єднати два 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.