Magento - modelo personalizado (não eav), carregado por vários campos

15

Eu tenho um modelo personalizado e um modelo de recursos. Quero carregar uma única instância do modelo usando mais de 1 campo.

O modelo possui os seguintes campos:

id
tag_name
custom_name
group_name

Desejo carregar este modelo com base em tag_name, custom_name e group_name em vez de id.

Atualmente, estou usando uma coleção e addFilter para cada campo. Isso funciona, mas eu me perguntei se existe uma estratégia padrão para esse tipo de coisa no Magento.

EDITAR

O magento principal parece não usar coleções para esse cenário, mas usa consultas sql diretas nos modelos de recursos.

um exemplo disso é:

loadByAccountAndDate() dentro Mage_Paypal_Model_Resource_Report_Settlement

Existe uma razão para isso, quando as coleções parecem ser uma maneira mais concisa, em termos de quantidade de código a ser gravado

Eu só não sei por que o magento escolhe fazer dessa maneira

Marty Wallace
fonte

Respostas:

21

Eu acho que essa é uma boa abordagem. Talvez você precise criar um wrapper na classe model para evitar escrever a mesma coisa repetidamente.
Algo como:

public function loadByMultiple($tag, $customName, $group){
    $collection = $this->getCollection()
            ->addFieldToFilter('tag_name', $tag)
            ->addFieldToFilter('custom_name', $customName)
            ->addFieldToFilter('group_name', $group);
    return $collection->getFirstItem();
}

E você pode carregar o item assim em qualquer outro lugar:

$model = Mage::getModel('model/class_here')->loadByMultiple($tag, $customName, $group);
if ($model->getId()){
   //the instance exists
}
else{
    //not found
}
Marius
fonte
Eu atualizei a minha pergunta com minhas preocupações sobre o uso de coleções
Marty Wallace
Se você realmente deseja excluir coleções da sua lógica, verifique o que o @mageUz escreveu em sua resposta. Não testei, mas parece uma boa ideia. Nota: Ainda não vejo problemas no uso de coleções.
Marius
Não é que eu gostaria de excluí-los, mas quero usar as melhores práticas do magento. Se o código principal estiver fazendo algo de uma maneira específica, normalmente isso deve ser um sinal de algo a seguir. Mas eu estou perguntando sobre este fórum para guidence como neste caso eu realmente não sei a melhor maneira
Marty Wallace
11
Também tenho preocupações com o uso de coleções neste caso. Presumivelmente, a coleção em questão tem _itemObjectClassa mesma que o modelo realmente está chamando loadByMultiple. Portanto, como resultado, não $x = Mage::getModel('some/model')seria uma instância de um modelo e $x->loadByMultiple($tag, $customName, $group)realmente seria uma instância nova / diferente?
Kojiro
@kojiro. Sim, será uma instância diferente, mas o mesmo acontece loadByAttribute. Veja esta pergunta para referência: magento.stackexchange.com/q/5926/146
Marius
7

Módulo / Modelo / SomeModel.php

public function loadByAttributes($attributes)
{
    $this->setData($this->getResource()->loadByAttributes($attributes));
    return $this;
}

Módulo / Modelo / Recurso / SomeModel.php:

public function loadByAttributes($attributes)
    {
        $adapter = $this->_getReadAdapter();
        $where   = array();
        foreach ($attributes as $attributeCode=> $value) {
            $where[] = sprintf('%s=:%s', $attributeCode, $attributeCode);
        }
        $select = $adapter->select()
            ->from($this->getMainTable())
            ->where(implode(' AND ', $where));

        $binds = $attributes;

        return $adapter->fetchRow($select, $binds);
    }

E, finalmente, você pode carregar o seguinte modelo:

$attributes = array('tag_name'=> 'any', 'custome_name'=> 'some','group_name'=>'some');
$model      = Mage::getModel('module/somemodel')->loadByAttributes($attributes);

Atualizada

A propósito, você pode usar esse método (loadByAttributes) facilmente, em vez de coletar e é mais compreensível. O Magento também despacha alguns eventos ao carregar a coleção ou entidade e a extensão de terceiros pode atualizar a coleção ou entidade pelo observador. Se você carregar a entidade por meio do recurso (dado no meu e no seu), nenhum evento / observador será acionado e você poderá obter a entidade "limpa" mais rapidamente, em vez de coletar. Além disso, o Magento não usa a coleção em cache dessa maneira, ele a carrega diretamente da tabela db.
Talvez seja por isso que use este método pelos módulos principais do Magento.

mageUz
fonte
Eu acho que está faltando um getData () nesta linha:, $this->setData($this->getResource()->loadByAttributes($attributes));que deve ser: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); Certo?
Mihai MATEI 11/11
2

Você está fazendo certo com addFilter. No Magento, você pode carregar por qualquer atributo, mas não por vários atributos ao mesmo tempo. Ao adicionar filtros, você obtém o mesmo efeito sem sobrecarga extra.

user487772
fonte
Usar um db select não seria melhor do que usar uma coleção?
Marty Wallace
O que você acha que addFilterestá fazendo? :-)
user487772
Você pode olhar para loadByAccountAndDate () in Mage_Paypal_Model_Resource_Report_Settlement como isso é usando uma escolha em vez de coleção
Marty Wallace
E, na verdade, essa situação em código do núcleo é quase exclusivamente como este e eu não posso ver qualquer coleções usando
Marty Wallace
11
Eu atualizei a minha pergunta com minhas preocupações sobre o uso de coleções
Marty Wallace
1

Em primeiro lugar - sua estratégia para filtrar uma coleção está correta. Como as coleções no Magento lazy-load, você tem a capacidade de criar métodos no seu modelo de recursos para definir com mais rigor os requisitos de sua carga personalizada.

Sem um pouco do seu código para amostra, considere o seguinte pseudo-método no seu Modelo de Recursos:

<?php


class Marty_Wallace_Model_Resource_Method extends Mage_Core_Model_Resource_Db_Abstract{

    protected function _construct()
    {
        $this->_init('yourmodel/table', 'entity_id');
    }

    public function loadByCriteria(array $filter)
    {

        //$filter should be array('columnname'=>'value','columname'=>'value')

        $collection = Mage::getModel('yourmodel/class')->getCollection();

        foreach($filter as $column=>$value){
            $collection->addFieldToFilter($column,$value);
        }

        return $collection;

    }
}
philwinkle
fonte
Eu atualizei a minha pergunta com meus preocupações sobre como usar coleções para este caso de uso particular, mas eu não tenho conhecimento suficiente para saber por que magento faz isso dessa maneira
Marty Wallace