Comment cloner la collection dans Magento?


12

J'ai une collection dans une méthode où je veux effectuer deux opérations différentes sur cette collection. Donc, je veux deux copies distinctes de la même collection, puis attribuer à nouveau l'une des deux collections à la collection d'origine et la renvoyer.

Pour simplifier, supposons que j'ai une collection d'objets appelée $collection.

Maintenant, je l'essaie avec le clonage PHP car je ne sais pas s'il existe un clonage de collection Magento intégré ou non.

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

Maintenant, j'essaie d'effectuer différentes opérations sur ces deux clones distincts de la collection d'origine, quelque chose comme.

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

Mais le plus étrange est que ces deux collections clonées ont toutes les deux les conditions assignées! La condition $ coll1 est appliquée à $ coll2 avec la condition de $ coll2, et vice versa.

Personne ne saurais comment achever cela?

Merci!

Réponses:


14

L'utilisation de l'opérateur de clonage PHP, où un clonage en profondeur est souhaité, nécessite des classes qui stockent des objets sur des propriétés implémentent une méthode __clone pour copier les objets. S'ils ne le définissent pas, les propriétés des deux instances feront référence au même objet.

Magento n'implémente pas __clone sur ses résumés de collection, et ne prend donc pas en charge le clonage en profondeur comme vous le souhaitez.

Ma suggestion est de chercher d'autres façons d'accomplir ce que vous voulez faire, car le clonage d'une collection pourrait être assez cher.

L'exemple que vous avez donné (par exemple) pourrait être changé pour cloner la sélection, la modifier pour sélectionner un nombre d'enregistrements qu'elle aurait chargé, puis en fonction de ce résultat, modifier la collection. Cela fonctionnerait également mieux car vous ne chargeriez pas une collection et ne la compteriez que pour déterminer celle à utiliser.

EDIT: ce qui suit montre comment récupérer un décompte sans charger ou modifier réellement la collection.

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

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}

Juste un petit détail: les informations de l'endroit sont enregistrées $collection->getSelect()et non dans la collection elle-même.
Fabian Blechschmidt

Merci de répondre. Mais après avoir appliqué la condition Where uniquement, je veux connaître le nombre de collectes, et sur la base de ce nombre uniquement, je veux décider d'utiliser ou non une condition Where différente. Pouvez-vous publier un extrait de code pour mieux comprendre comment le faire?
MagExt

Réponse mise à jour avec un exemple de code. Comme l'a souligné @FabianBlechschmidt, où est dans la sélection, qui est d'où vient votre problème spécifique car il n'est pas cloné lorsque l'objet de collection est cloné et les deux finissent par se référer à la même instance d'objet sélectionné.
davidalger

Merci pour la mise à jour. Je n'ai pas essayé ceci car j'ai déjà obtenu la solution quelque chose comme ça seulement.
MagExt

En fait, s'il y a un problème de clonage de la collection, sérialiser et désérialiser peut être utile dans le processus. Il existe également d'autres alternatives au clonage en PHP qui sont assez décentes. Mais dans l'ensemble, David a raison ... fondamentalement, lorsque vous clonez l'objet, vous clonez également les pointeurs sur les objets imbriqués qui lui sont attachés, bien que sa réponse n'ait pas correctement énoncé le problème sous-jacent.
mprototype

1

Pour développer la réponse de @ davidalger, vous pouvez réinitialiser la sélection si vous souhaitez effectuer une opération différente d'un compte - comme ceci:

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

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

Attention cependant, cela pourrait avoir des effets néfastes plus tard dans le processus car cela modifie la collection.

Une meilleure façon serait de cloner la sélection d'une manière ou d'une autre, mais une copie superficielle ne la couperait pas car l'objet contient des types complexes (Varien_Db_Select ni Zend_Db_Select ont une __cloneméthode).

Une façon de contourner ce problème consiste à enregistrer les données de sélection, à les modifier, à exécuter votre requête, puis à remettre les données de sélection d'origine.

Voir ici pour un exemple: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.