Como clonar a coleção no Magento?

12

Eu tenho uma coleção em um método em que desejo executar duas operações diferentes nessa coleção. Portanto, quero duas cópias separadas da mesma coleção e atribua uma das duas coleções à coleção original novamente e devolva-a.

Para simplificar, suponha que eu tenha uma coleção de objetos chamada $collection.

Agora, estou tentando com a clonagem de PHP, pois não sei se há alguma clonagem de coleção do Magento embutida ou não.

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

Agora, estou tentando executar operações diferentes nesses dois clones separados da coleção original, algo assim.

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

Mas o mais estranho é que essas duas coleções clonadas têm as condições where atribuídas! A condição $ coll1 é aplicada a $ coll2 junto com a condição de $ coll2 e vice-versa.

Alguém sabe como alcançar isso?

Obrigado!

MagExt
fonte

Respostas:

14

O uso do operador de clone do PHP, onde a clonagem profunda é desejada, requer classes que armazenam objetos nas propriedades implementam um método __clone para copiar os objetos. Se eles não o definirem, as propriedades nas duas instâncias farão referência ao mesmo objeto.

O Magento não implementa __clone em seus resumos de coleção e, portanto, não suporta clonagem profunda como você deseja.

Minha sugestão é procurar outras maneiras de realizar o que você deseja fazer, pois a clonagem de uma coleção pode ser bastante cara.

O exemplo que você deu (por exemplo) pode ser alterado para clonar a seleção, modificá-lo para selecionar uma contagem dos registros que ele teria carregado e, com base nesse resultado, modificar a coleção. Isso também teria um desempenho melhor, pois você não carregaria uma coleção e contaria apenas para determinar qual usar.

EDIT: O seguinte demonstra como obter uma contagem sem carregar ou modificar a coleção.

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

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}
davidalger
fonte
Apenas um pequeno detalhe: as informações do local são salvas $collection->getSelect()e não na coleção em si.
Fabian Blechschmidt
Obrigado pela resposta. Mas, depois de aplicar somente a condição where, quero saber a contagem da coleção e, com base nessa contagem, quero decidir se utilizarei diferente da condição where ou não. Você pode postar algum trecho de código para entender melhor como fazê-lo?
MagExt 23/05
Resposta atualizada com um exemplo de código. Como o @FabianBlechschmidt apontou, o where está no select, que é a origem do seu problema específico, pois não é clonado quando o objeto da coleção é clonado e ambos acabam se referindo à mesma instância do objeto select.
Davidalger #
Obrigado pela atualização. Eu não tentei isso, pois já consegui a solução apenas algo assim.
MagExt
Na verdade, se houver um problema ao clonar a coleção, serializar e desserializar podem ser úteis no processo. Existem também outras alternativas para clonar no PHP que são bastante decentes. Mas apesar de tudo, David está correto ... basicamente, quando você está clonando o objeto, também está clonando os ponteiros para os objetos aninhados anexados a ele, embora a resposta dele não tenha declarado adequadamente o problema subjacente.
Mprototype
1

Para expandir a resposta de @ davidalger, você pode redefinir o select se desejar fazer uma operação diferente de uma contagem - assim:

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

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

Tenha cuidado, porém, isso pode ter efeitos negativos mais tarde no processo, pois isso modifica a coleção.

Uma maneira melhor seria clonar a seleção de alguma forma, mas uma cópia superficial não a cortaria, pois o objeto contém tipos complexos (Varien_Db_Select nem Zend_Db_Select têm um __clonemétodo).

Uma maneira de contornar isso é salvar os dados selecionados, modificá-los, executar sua consulta e colocar de volta os dados selecionados originais.

Veja aqui um exemplo: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

Erfan
fonte