Magento - model niestandardowy (non eav), ładowany według wielu pól


15

Mam model niestandardowy i model zasobów. Chcę załadować pojedyncze wystąpienie modelu przy użyciu więcej niż 1 pola.

Model ma następujące pola:

id
tag_name
custom_name
group_name

Chcę załadować ten model na podstawie tag_name, custom_name i group_name zamiast id.

Obecnie używam kolekcji i addFilter dla każdego pola. To działa, ale zastanawiałem się, czy istnieje standardowa strategia dla tego typu rzeczy w Magento?

EDYTOWAĆ

Core magento wydaje się nie używać kolekcji w tym scenariuszu, ale zamiast tego używa bezpośrednich zapytań SQL w modelach zasobów.

przykładem tego jest:

loadByAccountAndDate() w Mage_Paypal_Model_Resource_Report_Settlement

Czy istnieje ku temu powód, gdy zbiory wydają się być bardziej zwięzłe, jeśli chodzi o ilość kodu do napisania

Po prostu nie wiem, dlaczego magento decyduje się to zrobić w ten sposób

Odpowiedzi:


22

Myślę, że to dobre podejście. Być może musisz utworzyć opakowanie w klasie modelu, aby uniknąć pisania tego samego w kółko.
Coś jak:

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

I możesz załadować ten przedmiot w dowolnym innym miejscu:

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

Zaktualizowałem swoje pytanie o moje obawy związane z używaniem kolekcji
Marty Wallace,

Jeśli naprawdę chcesz wykluczyć kolekcje ze swojej logiki, sprawdź, co napisał @mageUz w swojej odpowiedzi. Nie testowałem tego, ale szwy to dobry pomysł. Uwaga: nadal nie widzę problemów z korzystaniem z kolekcji.
Marius

Nie chodzi o to, że chciałbym je wykluczyć, ale chcę stosować najlepsze praktyki magento. Jeśli kod podstawowy robi coś w określony sposób, zazwyczaj powinien to być znak, że należy postępować. Ale proszę na tym forum o wskazówki, ponieważ w tym przypadku naprawdę nie znam najlepszego sposobu
Marty Wallace,

1
Mam również obawy dotyczące korzystania ze zbiorów w tym przypadku. Przypuszczalnie kolekcja, o której mowa _itemObjectClass, ma taki sam, jak model, który faktycznie wywołuje loadByMultiple. W rezultacie, czy nie byłby $x = Mage::getModel('some/model')to jeden przypadek modelu, a $x->loadByMultiple($tag, $customName, $group)właściwie inny / nowy egzemplarz?
kojiro

@kojiro. Tak, będzie to inna instancja, ale tak też jest loadByAttribute. Zobacz to pytanie w celach informacyjnych: magento.stackexchange.com/q/5926/146
Marius

7

Moduł / Model / SomeModel.php

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

Moduł / Model / Zasób / 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);
    }

I na koniec możesz załadować model:

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

Zaktualizowano

Nawiasem mówiąc, możesz łatwo użyć tej metody (loadByAttributes) zamiast gromadzenia i jest to bardziej zrozumiałe. Magento wywołuje także niektóre zdarzenia podczas ładowania kolekcji lub encji, a rozszerzenie strony trzeciej może aktualizować kolekcję lub encję przez obserwatora. Jeśli ładujesz byt za pomocą zasobu (podanego na przykładzie mojego i twojego), żadne zdarzenia / obserwatorzy nie strzelają i możesz uzyskać „czysty” byt szybciej niż gromadzenie. Również Magento nie używa w ten sposób kolekcji buforowanej, ładuje ją bezpośrednio z tabeli db.
Być może to jest powód zastosowania tej metody przez moduły podstawowe Magento.


Myślę, że brakuje ci metody getData () w tym wierszu: $this->setData($this->getResource()->loadByAttributes($attributes));która powinna brzmieć: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); prawda?
Mihai MATEI,

2

Robisz to dobrze addFilter. W Magento możesz ładować według dowolnego atrybutu, ale nie wielu atrybutów jednocześnie. Dodając filtry osiągasz ten sam efekt bez dodatkowego obciążenia.


Korzystanie z db select nie byłoby lepsze niż używanie kolekcji?
Marty Wallace,

Jak myślisz, co addFilterrobi? :-)
user487772

Czy możesz spojrzeć na loadByAccountAndDate () w Mage_Paypal_Model_Resource_Report_Settlement, ponieważ używa on wyboru zamiast kolekcji
Marty Wallace

I tak naprawdę ta sytuacja w kodzie podstawowym jest prawie wyłącznie taka i nie widzę żadnych korzystających z kolekcji
Marty Wallace

1
Zaktualizowałem swoje pytanie o moje obawy związane z używaniem kolekcji
Marty Wallace,

1

Po pierwsze - Twoja strategia filtrowania kolekcji jest poprawna. Ponieważ kolekcje w Magento leniwe ładowanie masz możliwość tworzenia metod w modelu zasobów, aby ściślej zdefiniować wymagania niestandardowego obciążenia.

Bez części kodu do próbkowania, weź pod uwagę następującą pseudo-metodę w swoim modelu zasobów:

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

    }
}

I zostały zaktualizowane moje pytanie z moimi obawami używając zbiory w tym konkretnym przypadku, ale nie mam wystarczającej wiedzy, aby wiedzieć, dlaczego Magento robi to w ten sposób
Marty Wallace
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.