Model Magento - custom (non eav), memuat beberapa bidang

15

Saya punya model khusus dan model sumber daya. Saya ingin memuat satu contoh model menggunakan lebih dari 1 bidang.

Model memiliki bidang-bidang berikut:

id
tag_name
custom_name
group_name

Saya ingin memuat model ini berdasarkan tag_name, custom_name, dan group_name, bukan id.

Saat ini saya menggunakan koleksi dan addFilter untuk setiap bidang. Ini berfungsi, tetapi saya bertanya-tanya apakah ada strategi standar untuk hal semacam ini di Magento?

EDIT

Core magento tampaknya tidak menggunakan koleksi untuk skenario ini, melainkan menggunakan kueri sql langsung dalam model sumber daya.

contoh dari ini adalah:

loadByAccountAndDate() di Mage_Paypal_Model_Resource_Report_Settlement

Apakah ada alasan untuk ini, ketika koleksi tampaknya menjadi cara yang lebih ringkas, dalam hal jumlah kode yang akan ditulis

Aku hanya tidak tahu mengapa Magento memilih untuk melakukannya dengan cara ini

Marty Wallace
sumber

Jawaban:

22

Saya pikir ini adalah pendekatan yang baik. Mungkin Anda perlu membuat pembungkus di kelas model sehingga Anda akan menghindari menulis hal yang sama berulang kali.
Sesuatu seperti:

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

Dan Anda dapat memuat item seperti ini di tempat lain:

$model = Mage::getModel('model/class_here')->loadByMultiple($tag, $customName, $group);
if ($model->getId()){
   //the instance exists
}
else{
    //not found
}
Marius
sumber
Saya telah memperbarui pertanyaan saya dengan keprihatinan saya tentang penggunaan koleksi
Marty Wallace
Jika Anda benar-benar ingin mengecualikan koleksi dari logika Anda, periksa apa yang @mageUz tulis dalam jawabannya. Saya tidak mengujinya, tetapi jahitannya seperti ide yang bagus. Catatan: Saya masih tidak melihat masalah dalam menggunakan koleksi.
Marius
Bukannya saya ingin mengecualikan mereka, tetapi saya ingin menggunakan praktik terbaik magento. Jika kode inti melakukan sesuatu dengan cara tertentu maka biasanya itu harus menjadi tanda sesuatu untuk diikuti. Tapi saya bertanya di forum ini untuk panduan seperti dalam kasus ini saya benar-benar tidak tahu cara terbaik
Marty Wallace
1
Saya juga memiliki masalah dalam menggunakan koleksi dalam hal ini. Agaknya koleksi yang dimaksud memiliki _itemObjectClassyang sama dengan model yang benar-benar memanggil loadByMultiple. Jadi sebagai hasilnya, tidak akan $x = Mage::getModel('some/model')menjadi satu contoh model dan $x->loadByMultiple($tag, $customName, $group)benar-benar menjadi contoh yang berbeda / baru?
kojiro
@kojiro. Ya itu akan menjadi contoh yang berbeda tetapi begitu juga loadByAttribute. Lihat pertanyaan ini untuk referensi: magento.stackexchange.com/q/5926/146
Marius
7

Module / Model / SomeModel.php

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

Modul / Model / Sumber Daya / 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);
    }

Dan akhirnya Anda dapat memuat model berikut:

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

Diperbarui

Omong-omong, Anda dapat menggunakan metode (loadByAttributes) ini dengan mudah daripada koleksi dan lebih mudah dimengerti. Magento juga mengirimkan beberapa acara saat memuat koleksi atau entitas dan ekstensi pihak ketiga dapat memperbarui koleksi atau entitas oleh pengamat. Jika Anda memuat entitas melalui sumber daya (diberikan sebagai contoh milik saya dan milik Anda) tidak ada kejadian / pengamat menyala dan Anda bisa mendapatkan entitas "bersih" lebih cepat daripada pengumpulan. Juga Magento tidak menggunakan koleksi cache dengan cara ini, ia memuatnya langsung dari tabel db.
Mungkin itulah alasan menggunakan metode ini oleh modul inti Magento.

mageUz
sumber
Saya pikir Anda melewatkan getData () pada baris ini:, $this->setData($this->getResource()->loadByAttributes($attributes));yang seharusnya: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); Benar?
Mihai MATEI
2

Anda melakukannya dengan benar addFilter. Di Magento Anda dapat memuat dengan atribut apa pun tetapi tidak sekaligus dengan banyak atribut. Dengan menambahkan filter, Anda mencapai efek yang sama tanpa overhead tambahan.

pengguna487772
sumber
Menggunakan db pilih tidak akan lebih baik daripada menggunakan koleksi?
Marty Wallace
Menurut Anda apa yang addFiltersedang dilakukan? :-)
user487772
Dapatkah Anda melihat loadByAccountAndDate () di Mage_Paypal_Model_Resource_Report_Settlement karena ini menggunakan koleksi pilih alih-alih koleksi
Marty Wallace
Dan sebenarnya situasi ini dalam kode inti hampir secara eksklusif seperti ini dan saya tidak dapat melihat menggunakan koleksi
Marty Wallace
1
Saya telah memperbarui pertanyaan saya dengan keprihatinan saya tentang penggunaan koleksi
Marty Wallace
1

Pertama - strategi Anda untuk memfilter koleksi sudah benar. Karena koleksi di Magento lazy-load, Anda memiliki kemampuan untuk membuat metode dalam model sumber daya Anda untuk lebih ketat menentukan persyaratan pemuatan khusus Anda.

Tanpa beberapa kode Anda untuk dijadikan sampel, pertimbangkan metode semu berikut dalam Model Sumber Daya Anda:

<?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
sumber
Saya telah memperbarui pertanyaan saya dengan keprihatinan saya tentang penggunaan koleksi untuk kasus penggunaan khusus ini tetapi saya tidak memiliki cukup pengetahuan untuk mengetahui mengapa magento melakukannya dengan cara ini
Marty Wallace