Как клонировать коллекцию в Magento?

12

У меня есть одна коллекция в методе, где я хочу выполнить две разные операции над этой коллекцией. Итак, я хочу получить две отдельные копии одной коллекции, а затем снова назначить одну из двух коллекций исходной коллекции и вернуть ее.

Для простоты предположим, что у меня есть коллекция объектов с именем $collection.

Теперь я пытаюсь сделать это с помощью клонирования PHP, так как не знаю, есть ли встроенное клонирование Magento или нет.

$coll1 = clone $collection;
$coll2 = clone $collection;

Сейчас я пытаюсь выполнить разные операции с этими двумя отдельными клонами оригинальной коллекции, что-то вроде.

$coll1->getSelect()->where('some where condition');
$coll2->getSelect()->where('some different where condition');
if($coll1->count() == 0) {
    $collection = $coll2;
} else {
    $collection = $coll1;
}

Но странность в том, что обе эти клонированные коллекции имеют оба назначенных условия! Условие $ coll1 применяется к $ coll2 вместе с условием $ coll2 и наоборот.

Кто-нибудь знает, как этого добиться?

Благодарность!

MagExt
источник

Ответы:

14

Использование оператора клонирования PHP, где требуется глубокое клонирование, требует классов, которые хранят объекты в свойствах, реализующих метод __clone для копирования объектов. Если они не определяют его, свойства в обоих экземплярах будут ссылаться на один и тот же объект.

Magento не реализует __clone в своих сборниках, и поэтому не поддерживает глубокое клонирование, как вы этого хотите.

Мое предложение состоит в том, чтобы искать другие способы выполнить то, что вы хотите сделать, поскольку клонирование коллекции может быть довольно дорогим.

Пример, который вы привели (например), можно изменить, чтобы клонировать выбор, изменить его, чтобы выбрать количество записей, которые он бы загрузил, и затем на основе этого результата изменить коллекцию. Это также будет работать лучше, поскольку вы не будете загружать коллекцию и считать ее только для того, чтобы определить, какую из них использовать.

РЕДАКТИРОВАТЬ: Ниже показано, как получить счет без загрузки или изменения коллекции.

$collection = Mage::getModel(...)->getCollection();

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}
davidalger
источник
Небольшая деталь: информация о том, где хранится, $collection->getSelect()а не в самой коллекции.
Фабиан Блехшмидт
Спасибо за ответ. Но после применения условия «только где» я хочу узнать количество сборов, и на основе только этого количества я хочу решить, использовать ли другое условие «где» или нет. Можете ли вы опубликовать фрагмент кода, чтобы лучше понять, как это сделать?
MagExt
Обновленный ответ с примером кода. Как указывало @FabianBlechschmidt, где находится выбор, где и возникает ваша конкретная проблема, поскольку он не клонируется, когда клонируется объект коллекции, и оба в конечном итоге ссылаются на один и тот же экземпляр объекта выбора.
Давидгер
Спасибо за обновление. Я не пробовал это, поскольку я уже получил решение что-то подобное.
MagExt
На самом деле, если существует проблема клонирования коллекции, сериализация и десериализация могут быть полезны в этом процессе. Есть и другие альтернативы клонированию в PHP, которые вполне приличны. Но в целом Дэвид прав: в основном, когда вы клонируете объект, вы клонируете указатели на вложенные Объекты, также прикрепленные к нему, хотя в его ответе неправильно указана основная проблема.
mprototype
1

Чтобы расширить ответ @ davidalger, вы можете сбросить выбор, если хотите выполнить операцию, отличную от подсчета, например:

$select= $collection->getSelectCountSql()->reset();

$select
    ->from('newsletter_subscriber', array('some_column'))
    ->distinct();

Будьте осторожны, это может иметь пагубные последствия на более поздних этапах процесса, поскольку это изменяет коллекцию.

Лучшим способом было бы как-то клонировать выделение, но мелкая копия не обрезала бы его, поскольку объект содержит сложные типы (у Varien_Db_Select или Zend_Db_Select есть __cloneметод).

Один из способов обойти это - сохранить выбранные данные, изменить их, выполнить запрос, а затем вернуть исходные выбранные данные.

Смотрите здесь для примера: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

Erfan
источник