Come clonare la collezione in Magento?


12

Ho una raccolta in un metodo in cui voglio eseguire due diverse operazioni su questa raccolta. Quindi, voglio due copie separate della stessa raccolta, quindi assegnare nuovamente una delle due raccolte alla raccolta originale e restituirla.

Per semplificare questo, supponiamo di avere una raccolta di oggetti chiamata $collection.

Ora, lo sto provando con la clonazione di PHP in quanto non so se esiste una clonazione di raccolte Magento incorporata o meno.

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

Ora sto cercando di eseguire diverse operazioni su questi due cloni separati della collezione originale, qualcosa del genere.

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

Ma la cosa strana è che entrambe queste raccolte clonate hanno entrambe le condizioni assegnate dove! La condizione $ coll1 viene applicata a $ coll2 insieme alla condizione di $ coll2 e viceversa.

Qualcuno sa come raggiungere questo obiettivo?

Grazie!

Risposte:


14

L'uso dell'operatore clone PHP, dove si desidera la clonazione profonda, richiede classi che memorizzano oggetti su proprietà implementano un metodo __clone per copiare gli oggetti. Se non lo definiscono, le proprietà di entrambe le istanze faranno riferimento allo stesso oggetto.

Magento non implementa __clone sui suoi abstract di raccolta e pertanto non supporta la clonazione profonda come desideri.

Il mio suggerimento è di cercare altri modi per realizzare ciò che si desidera fare, poiché la clonazione di una raccolta potrebbe essere piuttosto costosa.

L'esempio che hai fornito (ad esempio) potrebbe essere modificato per clonare la selezione, modificarlo per selezionare un conteggio dei record che avrebbe caricato e quindi in base a quel risultato modificare la raccolta. Ciò funzionerebbe anche meglio poiché non caricheresti una collezione e non la conteresti solo per determinare quale utilizzare.

MODIFICA: Di seguito viene illustrato come acquisire un conteggio senza caricare o modificare effettivamente la raccolta.

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

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

Solo un piccolo dettaglio: le informazioni su dove vengono salvate $collection->getSelect()e non nella raccolta stessa.
Fabian Blechschmidt

Grazie per la risposta. Ma dopo aver applicato solo dove condizione voglio sapere il conteggio delle raccolte e basandomi solo su quel conteggio voglio decidere se usare diverse condizioni dove o meno. Puoi pubblicare uno snippet di codice per capire meglio come farlo?
MagExt

Risposta aggiornata con un esempio di codice. Come ha sottolineato @FabianBlechschmidt, il punto in cui si trova la selezione, da dove proviene il tuo problema specifico poiché non viene clonato quando l'oggetto della raccolta viene clonato ed entrambi finiscono per fare riferimento alla stessa istanza di oggetto selezionato.
davidalger,

Grazie per l'aggiornamento Non ho provato questo perché ho già ottenuto la soluzione solo qualcosa del genere.
MagExt

In realtà, se si verifica un problema durante la clonazione della raccolta, serializzare e annullare la serializzazione può essere utile nel processo. Ci sono anche altre alternative al clone in PHP che sono abbastanza decenti. Ma tutto sommato David ha ragione ... fondamentalmente quando stai clonando l'oggetto stai clonando anche i puntatori agli oggetti nidificati ad esso collegati, anche se la sua risposta non ha indicato correttamente il problema di fondo.
mprototype,

1

Per espandere la risposta di @ davidalger, è possibile reimpostare la selezione se si desidera eseguire un'operazione diversa da un conteggio, in questo modo:

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

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

Attenzione però, questo potrebbe avere effetti dannosi più avanti nel processo poiché questo modifica la raccolta.

Un modo migliore sarebbe clonare in qualche modo la selezione, ma una copia superficiale non la taglierebbe poiché l'oggetto contiene tipi complessi (Varien_Db_Select e Zend_Db_Select hanno un __clonemetodo).

Un modo per aggirare il problema è salvare i dati selezionati, modificarli, eseguire la query, quindi ripristinare i dati originali selezionati.

Vedi qui per un esempio: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.