Magento - modello personalizzato (non eav), caricato da più campi


15

Ho un modello personalizzato e un modello di risorse. Voglio caricare una singola istanza del modello usando più di 1 campo.

Il modello ha i seguenti campi:

id
tag_name
custom_name
group_name

Voglio caricare questo modello basato su tag_name, custom_name e group_name anziché id.

Attualmente sto usando una raccolta e un filtro aggiuntivo per ogni campo. Funziona, ma mi chiedevo se ci fosse una strategia standard per questo tipo di cose in Magento?

MODIFICARE

Il core magento sembra non utilizzare le raccolte per questo scenario, ma utilizza invece query sql dirette nei modelli di risorse.

un esempio di questo è:

loadByAccountAndDate() nel Mage_Paypal_Model_Resource_Report_Settlement

C'è una ragione per questo, quando le raccolte sembrano essere un modo più conciso, in termini di quantità di codice da scrivere

Non so perché Magento scelga di farlo in questo modo

Risposte:


22

Penso che questo sia un buon approccio. Forse è necessario creare un wrapper nella classe del modello in modo da evitare di scrivere sempre la stessa cosa.
Qualcosa di simile a:

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 puoi caricare l'articolo in questo modo in qualsiasi altro posto:

$model = Mage::getModel('model/class_here')->loadByMultiple($tag, $customName, $group);
if ($model->getId()){
   //the instance exists
}
else{
    //not found
}

Ho aggiornato la mia domanda con le mie preoccupazioni sull'uso delle raccolte
Marty Wallace,

Se vuoi davvero escludere le raccolte dalla tua logica, controlla cosa ha scritto @mageUz nella sua risposta. Non l'ho provato, ma le cuciture sembrano una buona idea. Nota: non vedo ancora problemi nell'uso delle raccolte.
Marius

Non è che vorrei escluderli, ma voglio usare le migliori pratiche di magento. Se il codice principale sta facendo qualcosa in un modo particolare, in genere dovrebbe essere un segno di qualcosa da seguire. Ma sto chiedendo la prova su questo forum perché in questo caso non conosco davvero il modo migliore
Marty Wallace,

1
In questo caso ho anche dubbi sull'utilizzo delle raccolte. Presumibilmente la collezione in questione ha un valore _itemObjectClassidentico a quello che il modello sta effettivamente chiamando loadByMultiple. Di conseguenza, non $x = Mage::getModel('some/model')sarebbe un'istanza di un modello e in $x->loadByMultiple($tag, $customName, $group)realtà sarebbe un'istanza diversa / nuova?
Kojiro,

@kojiro. Sì, sarà un'istanza diversa, ma lo è anche loadByAttribute. Vedi questa domanda per riferimento: magento.stackexchange.com/q/5926/146
Marius

7

Modulo / Modello / SomeModel.php

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

Modulo / Modello / Resource / 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 infine puoi caricare il modello seguente:

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

aggiornato

A proposito, puoi usare questo metodo (loadByAttributes) facilmente piuttosto che la raccolta ed è più comprensibile. Magento invia anche alcuni eventi durante il caricamento della raccolta o dell'entità e l'estensione di terze parti può aggiornare la raccolta o l'entità dall'osservatore. Se carichi l'entità tramite la risorsa (fornita nell'esempio del mio e del tuo) nessun evento / osservatore si attiva e puoi ottenere un'entità "pulita" più velocemente invece che la raccolta. Inoltre Magento non utilizza la raccolta cache in questo modo, lo carica direttamente dalla tabella db.
Forse è per questo motivo che questo metodo viene utilizzato dai moduli core di Magento.


Penso che ti manchi un getData () su questa linea:, $this->setData($this->getResource()->loadByAttributes($attributes));che dovrebbe essere: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); giusto?
Mihai MATEI,

2

Lo stai facendo bene con addFilter. In Magento puoi caricare qualsiasi attributo ma non più attributi contemporaneamente. Aggiungendo filtri si ottiene lo stesso effetto senza costi aggiuntivi.


Usare una selezione db non sarebbe meglio che usare una collezione?
Marty Wallace,

Cosa pensi che addFilterstia facendo? :-)
user487772

Puoi vedere loadByAccountAndDate () in Mage_Paypal_Model_Resource_Report_Settlement in quanto utilizza un comando di selezione anziché una raccolta
Marty Wallace,

E in realtà questa situazione nel codice core è quasi esclusivamente così e non riesco a vedere alcun utilizzo di raccolte
Marty Wallace,

1
Ho aggiornato la mia domanda con le mie preoccupazioni sull'uso delle raccolte
Marty Wallace,

1

Innanzitutto, la tua strategia per filtrare una raccolta è corretta. Poiché le raccolte in Magento-lazy-load hai la possibilità di creare metodi nel tuo modello di risorsa per definire più strettamente i requisiti del tuo carico personalizzato.

Senza parte del codice da campionare, prendere in considerazione il seguente pseudo-metodo nel modello di risorsa:

<?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;

    }
}

Ho aggiornato la mia domanda con le mie preoccupazioni sull'uso delle raccolte per questo particolare caso d'uso, ma non ho abbastanza conoscenze per sapere perché Magento lo fa in questo modo
Marty Wallace,
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.