Magento - Benutzerdefiniertes (Nicht-EAV) Modell, das durch mehrere Felder geladen wird

15

Ich habe ein benutzerdefiniertes Modell und ein Ressourcenmodell. Ich möchte eine einzelne Instanz des Modells mit mehr als einem Feld laden.

Das Modell hat folgende Felder:

id
tag_name
custom_name
group_name

Ich möchte dieses Modell basierend auf tag_name, custom_name und group_name anstelle von id laden.

Derzeit verwende ich eine Sammlung und AddFilter für jedes Feld. Das funktioniert, aber ich habe mich gefragt, ob es in Magento eine Standardstrategie für diese Art von Dingen gibt.

BEARBEITEN

Core Magento scheint für dieses Szenario keine Sammlungen zu verwenden, sondern verwendet direkte SQL-Abfragen in den Ressourcenmodellen.

Ein Beispiel hierfür ist:

loadByAccountAndDate() im Mage_Paypal_Model_Resource_Report_Settlement

Gibt es einen Grund dafür, wenn Sammlungen in Bezug auf die Menge des zu schreibenden Codes übersichtlicher erscheinen?

Ich weiß nur nicht, warum Magento es so macht

Marty Wallace
quelle

Antworten:

21

Ich halte das für einen guten Ansatz. Möglicherweise müssen Sie einen Wrapper in der Modellklasse erstellen, damit Sie nicht immer wieder dasselbe schreiben.
Etwas wie:

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

Und Sie können den Artikel wie folgt an einem anderen Ort laden:

$model = Mage::getModel('model/class_here')->loadByMultiple($tag, $customName, $group);
if ($model->getId()){
   //the instance exists
}
else{
    //not found
}
Marius
quelle
Ich habe meine Frage mit meinen Bedenken bezüglich der Verwendung von Sammlungen aktualisiert
Marty Wallace
Wenn Sie Sammlungen wirklich von Ihrer Logik ausschließen möchten, überprüfen Sie, was @mageUz in seiner Antwort geschrieben hat. Ich habe es nicht getestet, aber eine gute Idee. Hinweis: Ich sehe immer noch keine Probleme bei der Verwendung von Sammlungen.
Marius
Es ist nicht so, dass ich sie ausschließen möchte, aber ich möchte die besten Praktiken von Magento anwenden. Wenn der Kerncode etwas auf eine bestimmte Weise tut, sollte dies in der Regel ein Zeichen dafür sein, dass etwas zu befolgen ist. Aber ich bitte in diesem Forum um Rat, da ich in diesem Fall wirklich nicht den besten Weg kenne
Marty Wallace
1
Ich habe auch Bedenken, in diesem Fall Sammlungen zu verwenden. Vermutlich hat die fragliche Sammlung eine _itemObjectClass, die der des tatsächlich aufrufenden Modells entspricht loadByMultiple. Wäre dies nicht $x = Mage::getModel('some/model')eine Instanz eines Modells und $x->loadByMultiple($tag, $customName, $group)tatsächlich eine andere / neue Instanz?
Kojiro
@kojiro. Ja, es wird eine andere Instanz sein, aber das tut es auch loadByAttribute. Siehe diese Frage als Referenz: magento.stackexchange.com/q/5926/146
Marius
6

Modul / Modell / SomeModel.php

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

Modul / Modell / Ressource / 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);
    }

Und schließlich können Sie folgendes Modell laden:

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

Aktualisiert

Übrigens können Sie diese (loadByAttributes) -Methode einfach anstelle einer Sammlung verwenden, und sie ist verständlicher. Magento löst auch einige Ereignisse aus, während die Sammlung oder Entität geladen wird, und die Erweiterung eines Drittanbieters kann die Sammlung oder Entität nach Beobachter aktualisieren. Wenn Sie die Entität über eine Ressource laden (in meinem und Ihrem Beispiel angegeben), wird kein Ereignis / Beobachter ausgelöst, und Sie können schneller eine "saubere" Entität erhalten als eine Sammlung. Außerdem verwendet Magento die zwischengespeicherte Sammlung nicht auf diese Weise, sondern lädt sie direkt aus der DB-Tabelle.
Vielleicht ist das der Grund, warum diese Methode von Magento-Kernmodulen verwendet wird.

mageUz
quelle
Ich denke, Sie vermissen ein getData () in dieser Zeile:, $this->setData($this->getResource()->loadByAttributes($attributes));das sollte sein: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); Richtig?
Mihai MATEI
2

Du machst es richtig mit addFilter. In Magento können Sie nach jedem Attribut aber nicht nach mehreren Attributen gleichzeitig laden. Durch Hinzufügen von Filtern erzielen Sie den gleichen Effekt ohne zusätzlichen Aufwand.

user487772
quelle
Die Verwendung einer Datenbankauswahl wäre nicht besser als die Verwendung einer Sammlung?
Marty Wallace
Was denkst du addFiltermacht das? :-)
user487772
Sehen Sie sich loadByAccountAndDate () in Mage_Paypal_Model_Resource_Report_Settlement an, da hier eine Auswahl anstelle einer Sammlung verwendet wird
Marty Wallace,
Und tatsächlich ist diese Situation im Kerncode fast ausschließlich so und ich kann keine mit Sammlungen sehen
Marty Wallace
1
Ich habe meine Frage mit meinen Bedenken über die Verwendung von Sammlungen aktualisiert
Marty Wallace
1

Erstens: Ihre Strategie zum Filtern einer Sammlung ist richtig. Da Sammlungen in Magento verzögert geladen werden, können Sie Methoden in Ihrem Ressourcenmodell erstellen, um die Anforderungen Ihrer benutzerdefinierten Ladung genauer zu definieren.

Berücksichtigen Sie in Ihrem Ressourcenmodell die folgende Pseudomethode, ohne dass Sie einen Teil Ihres Codes testen müssen:

<?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
quelle
Ich habe meine Frage mit meinen Bedenken bezüglich der Verwendung von Sammlungen für diesen bestimmten Anwendungsfall aktualisiert, aber ich habe nicht genug Wissen, um zu wissen, warum Magento dies so macht
Marty Wallace,