Wie klone ich die Sammlung in Magento?

12

Ich habe eine Sammlung in einer Methode, in der ich zwei verschiedene Vorgänge für diese Sammlung ausführen möchte. Ich möchte also zwei separate Kopien derselben Sammlung und ordne dann eine der beiden Sammlungen wieder der ursprünglichen Sammlung zu und sende sie zurück.

Nehmen wir zur Vereinfachung an, ich habe eine Objektauflistung mit dem Namen $collection.

Jetzt versuche ich es mit PHP-Klonen, da ich nicht weiß, ob eine Magento-Sammlung eingebaut ist oder nicht.

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

Jetzt versuche ich, verschiedene Operationen an diesen beiden separaten Klonen der ursprünglichen Sammlung durchzuführen, so etwas wie.

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

Aber das Seltsame ist, dass diese beiden geklonten Sammlungen beide Bedingungen haben! Die Bedingung $ coll1 wird zusammen mit der Bedingung $ coll2 auf $ coll2 angewendet und umgekehrt.

Weiß jemand, wie man das erreicht?

Vielen Dank!

MagExt
quelle

Antworten:

14

Die Verwendung des PHP-Klon-Operators erfordert, dass Klassen, die Objekte in Eigenschaften speichern, eine __clone-Methode implementieren, um die Objekte zu kopieren. Wenn sie es nicht definieren, verweisen die Eigenschaften auf beiden Instanzen auf dasselbe Objekt.

Magento implementiert __clone nicht in seinen Sammlungszusammenfassungen und unterstützt daher kein Deep Cloning, wie Sie es möchten.

Mein Vorschlag ist, nach anderen Möglichkeiten zu suchen, um das zu erreichen, was Sie tun möchten, da das Klonen einer Sammlung ziemlich teuer sein kann.

Das Beispiel, das Sie angegeben haben, könnte geändert werden, um die Auswahl zu klonen, zu ändern, um eine Anzahl der Datensätze auszuwählen, die geladen worden wären, und dann basierend auf diesem Ergebnis die Sammlung zu ändern. Dies führt auch zu einer besseren Leistung, da Sie eine Sammlung nicht laden und sie nur zählen, um zu bestimmen, welche verwendet werden soll.

BEARBEITEN: Im Folgenden wird gezeigt, wie Sie eine Zählung erfassen, ohne die Sammlung zu laden oder tatsächlich zu ändern.

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

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}
Davidalger
quelle
Nur ein kleines Detail: Die Informationen zum Speicherort werden in $collection->getSelect()und nicht in der Sammlung selbst gespeichert .
Fabian Blechschmidt
Danke für die Antwort. Aber nachdem ich nur die WHERE-Bedingung angewendet habe, möchte ich die Anzahl der Sammlungen wissen, und basierend auf dieser Anzahl möchte ich entscheiden, ob ich eine andere WHERE-Bedingung verwenden möchte oder nicht. Können Sie ein Code-Snippet posten, um besser zu verstehen, wie es geht?
MagExt
Aktualisierte Antwort mit einem Codebeispiel. Wie @FabianBlechschmidt hervorhob, befindet sich die Position in der Auswahl, von der Ihre spezifischen Probleme ausgehen, da sie nicht geklont werden, wenn das Auflistungsobjekt geklont wird, und beide am Ende auf dieselbe ausgewählte Objektinstanz verweisen.
Davidalger
Danke für Update. Ich habe das nicht ausprobiert, da ich die Lösung schon nur so bekommen habe.
MagExt
Tatsächlich kann beim Klonen der Sammlung das Serialisieren und unserialisieren hilfreich sein. Es gibt auch andere Alternativen zum Klonen in PHP, die ziemlich anständig sind. Aber alles in allem ist David richtig ... im Grunde genommen klonen Sie beim Klonen des Objekts die Zeiger auf die verschachtelten Objekte, die daran angehängt sind, obwohl in seiner Antwort das zugrunde liegende Problem nicht richtig angegeben wurde.
Prototyp
1

Um die Antwort von @ davidalger zu erweitern, können Sie die Auswahl zurücksetzen , wenn Sie eine andere Operation als eine Zählung ausführen möchten:

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

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

Seien Sie jedoch vorsichtig, da dies zu einem späteren Zeitpunkt nachteilige Auswirkungen haben kann, da dadurch die Sammlung geändert wird.

Ein besserer Weg wäre, das Select irgendwie zu klonen, aber eine flache Kopie würde es nicht schneiden, da das Objekt komplexe Typen enthält (Varien_Db_Select oder Zend_Db_Select haben eine __cloneMethode).

Eine Möglichkeit, dies zu umgehen, besteht darin, die ausgewählten Daten zu speichern, zu ändern, Ihre Abfrage auszuführen und dann die ursprünglichen ausgewählten Daten wiederherzustellen.

Ein Beispiel finden Sie hier: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

Erfan
quelle