Jak sklonować kolekcję w Magento?

12

Mam jedną kolekcję w metodzie, w której chcę wykonać dwie różne operacje na tej kolekcji. Tak więc chcę dwie osobne kopie tej samej kolekcji, a następnie ponownie przypisać jedną z dwóch kolekcji do oryginalnej kolekcji i zwrócić ją.

Aby to uprościć, załóżmy, że mam kolekcję obiektów o nazwie $collection.

Teraz próbuję z klonowaniem PHP, ponieważ nie wiem, czy jest wbudowane klonowanie kolekcji Magento, czy nie.

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

Teraz próbuję wykonać różne operacje na tych dwóch osobnych klonach oryginalnej kolekcji, coś w tym rodzaju.

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

Ale dziwne jest to, że obie sklonowane kolekcje mają oba przypisane warunki! Warunek $ coll1 jest stosowany do $ coll2 wraz z warunkiem $ coll2 i odwrotnie.

Czy ktoś wie, jak to osiągnąć?

Dzięki!

MagExt
źródło

Odpowiedzi:

14

Użycie operatora klonowania PHP, gdzie pożądane jest głębokie klonowanie, wymaga, aby klasy przechowujące obiekty we właściwościach zaimplementowały metodę __clone do skopiowania obiektów. Jeśli go nie zdefiniują, właściwości w obu instancjach będą odwoływały się do tego samego obiektu.

Magento nie implementuje __clone w swoich streszczeniach kolekcji i dlatego nie obsługuje głębokiego klonowania, jak chcesz.

Moją sugestią jest poszukiwanie innych sposobów na osiągnięcie tego, co chcesz zrobić, ponieważ klonowanie kolekcji może być dość drogie.

Podany przykład (na przykład) można zmienić, aby sklonować zaznaczenie, zmodyfikować go, aby wybrać liczbę załadowanych rekordów, a następnie zmodyfikować kolekcję na podstawie tego wyniku. Działałoby to również lepiej, ponieważ nie ładowałbyś kolekcji i nie liczyłbyś jej tylko w celu ustalenia, której użyć.

EDYCJA: Poniżej pokazano, jak pobrać liczbę bez ładowania lub faktycznej modyfikacji kolekcji.

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

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}
davidalger
źródło
Tylko mały szczegół: informacja o tym, gdzie jest zapisana, $collection->getSelect()a nie w samej kolekcji.
Fabian Blechschmidt
Dziękuję za odpowiedź. Ale po zastosowaniu tylko warunku chcę poznać liczbę kolekcji i na podstawie tej liczby chcę zdecydować, czy użyć innego warunku, czy nie. Czy możesz opublikować fragment kodu, aby lepiej zrozumieć, jak to zrobić?
MagExt
Zaktualizowana odpowiedź z przykładem kodu. Jak wskazał @FabianBlechschmidt, gdzie jest w select, stąd bierze się twój konkretny problem, ponieważ nie jest on klonowany podczas klonowania obiektu kolekcji i oba odnoszą się do tej samej instancji obiektu select.
davidalger
Dzięki za aktualizację. Nie próbowałem tego, ponieważ mam już rozwiązanie tylko takie.
MagExt
W rzeczywistości, jeśli występuje problem z klonowaniem kolekcji, serializacja i odserializacja mogą być pomocne w tym procesie. Istnieją również inne alternatywy do klonowania w PHP, które są całkiem przyzwoite. Ale w sumie David ma rację ... w zasadzie, gdy klonujesz obiekt, klonujesz również wskaźniki do dołączonych do niego Zagnieżdżonych Obiektów, chociaż jego odpowiedź nie określała właściwie problemu.
mprototyp
1

Aby rozwinąć odpowiedź @ davidalger, możesz zresetować zaznaczenie, jeśli chcesz wykonać inną operację niż liczenie - na przykład:

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

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

Uważaj jednak, może to mieć szkodliwe skutki na późniejszym etapie procesu, ponieważ modyfikuje to kolekcję.

Lepszym sposobem byłoby jakoś sklonowanie zaznaczenia, ale płytka kopia nie wyciąłaby go, ponieważ obiekt zawiera złożone typy (Varien_Db_Select ani Zend_Db_Select mają __clonemetodę).

Jednym ze sposobów obejścia tego jest zapisanie wybranych danych, zmodyfikowanie ich, uruchomienie zapytania, a następnie przywrócenie oryginalnych wybranych danych.

Zobacz tutaj przykład: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

Erfan
źródło