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

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
}

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.


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.


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;

    }
}

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.