Magento รุ่นที่กำหนดเอง (ไม่ใช่ eav), โหลดได้หลายช่อง


15

ฉันมีโมเดลที่กำหนดเองและโมเดลของทรัพยากร ฉันต้องการโหลดอินสแตนซ์เดียวของโมเดลโดยใช้มากกว่า 1 ฟิลด์

โมเดลมีฟิลด์ต่อไปนี้:

id
tag_name
custom_name
group_name

ฉันต้องการโหลดโมเดลนี้โดยยึดตาม tag_name, custom_name และ group_name แทนที่จะเป็น id

ขณะนี้ฉันกำลังใช้คอลเล็กชันและ addFilter สำหรับแต่ละฟิลด์ ใช้งานได้ แต่ฉันสงสัยว่ามีกลยุทธ์มาตรฐานสำหรับสิ่งประเภทนี้ใน Magento หรือไม่?

แก้ไข

Core magento ดูเหมือนจะไม่ใช้คอลเลกชันสำหรับสถานการณ์นี้ แต่ใช้การสอบถาม sql โดยตรงในโมเดลทรัพยากร

ตัวอย่างของสิ่งนี้คือ:

loadByAccountAndDate() ใน Mage_Paypal_Model_Resource_Report_Settlement

มีเหตุผลสำหรับสิ่งนี้เมื่อคอลเลกชันดูเหมือนจะเป็นวิธีที่กระชับมากขึ้นในแง่ของจำนวนรหัสที่จะเขียน

ฉันไม่รู้ว่าทำไมวีโอไอพีถึงเลือกทำแบบนี้

คำตอบ:


22

ฉันคิดว่านี่เป็นวิธีการที่ดี บางทีคุณต้องสร้างเสื้อคลุมในคลาสโมเดลเพื่อหลีกเลี่ยงการเขียนสิ่งเดียวกันซ้ำแล้วซ้ำอีก
สิ่งที่ต้องการ:

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

และคุณสามารถโหลดรายการเช่นนี้ได้ในที่อื่น ๆ :

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

ฉันได้อัปเดตคำถามของฉันพร้อมข้อสงสัยเกี่ยวกับการใช้คอลเล็กชันแล้ว
Marty Wallace

หากคุณต้องการแยกคอลเลกชันออกจากลอจิกของคุณให้ตรวจสอบสิ่งที่ @mageUz เขียนไว้ในคำตอบของเขา ฉันไม่ได้ทดสอบ แต่ตะเข็บเหมือนความคิดที่ดี หมายเหตุ: ฉันยังไม่เห็นปัญหาใด ๆ ในการใช้คอลเล็กชัน
Marius

ไม่ใช่ว่าฉันต้องการแยกพวกเขา แต่ฉันต้องการใช้แนวทางปฏิบัติที่ดีที่สุดของคุณภาพเยี่ยม หากรหัสหลักกำลังทำบางสิ่งในวิธีเฉพาะโดยทั่วไปนั่นควรเป็นสัญญาณของบางสิ่งที่จะต้องปฏิบัติตาม แต่ฉันถามในฟอรั่มนี้เพื่อความมั่นใจในกรณีนี้ฉันไม่รู้วิธีที่ดีที่สุดจริงๆ
Marty Wallace

1
ฉันยังมีข้อกังวลในการใช้คอลเล็กชันในกรณีนี้ สันนิษฐานคอลเลกชันในคำถามมีว่าเป็นเช่นเดียวกับรูปแบบการโทรจริง_itemObjectClass loadByMultipleดังนั้นผลลัพธ์จะไม่$x = Mage::getModel('some/model')เป็นหนึ่งอินสแตนซ์ของโมเดลและ$x->loadByMultiple($tag, $customName, $group)จริง ๆ แล้วเป็นอินสแตนซ์อื่น / ใหม่
kojiro

@kojiro ใช่มันจะเป็นอีกตัวอย่างloadByAttributeหนึ่ง ดูคำถามนี้สำหรับการอ้างอิง: magento.stackexchange.com/q/5926/146
Marius

7

โมดูล / รุ่น / SomeModel.php

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

โมดูล / รุ่น / ทรัพยากร / 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);
    }

และในที่สุดคุณสามารถโหลดโมเดลต่อไปนี้:

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

Updated

โดยวิธีการที่คุณสามารถใช้วิธีนี้ (loadByAttributes) ได้อย่างง่ายดายมากกว่าการเก็บรวบรวมและเป็นที่เข้าใจได้มากขึ้น วีโอไอพียังยื้อเหตุการณ์บางอย่างในขณะที่การโหลดคอลเลกชันหรือนิติบุคคลและส่วนขยายของบุคคลที่สามสามารถอัปเดตคอลเลกชันหรือเอนทิตี้โดยผู้สังเกตการณ์ หากคุณโหลดเอนทิตีผ่านทรัพยากร (ที่กำหนดไว้ในตัวอย่างของฉันและของคุณ) ไม่มีเหตุการณ์ / ผู้สังเกตการณ์ยิงและคุณจะได้เอนทิตี "สะอาด" เร็วกว่าการรวบรวม วีโอไอพียังไม่ได้ใช้คอลเลกชันแคชด้วยวิธีนี้มันโหลดโดยตรงจากตาราง db
อาจเป็นเหตุผลของการใช้วิธีนี้โดยโมดูลหลักของวีโอไอพี


ฉันคิดว่าคุณไม่มี getData () ในบรรทัดนี้: $this->setData($this->getResource()->loadByAttributes($attributes));ซึ่งควรเป็น: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); ใช่ไหม?
หมดเวลา MATEI

2

addFilterคุณกำลังทำมันถูกต้องกับ ใน Magento คุณสามารถโหลดโดยใช้แอตทริบิวต์ใดก็ได้ แต่ไม่สามารถใช้หลายคุณสมบัติพร้อมกันได้ ด้วยการเพิ่มตัวกรองคุณจะได้รับผลกระทบเดียวกันโดยไม่มีค่าใช้จ่ายเพิ่มเติม


การใช้ตัวเลือก db จะไม่ดีไปกว่าการใช้คอลเล็กชัน?
Marty Wallace

คุณคิดว่าaddFilterกำลังทำอะไร :-)
user487772

คุณสามารถดู loadByAccountAndDate () ใน Mage_Paypal_Model_Resource_Report_Settlement เนื่องจากใช้ตัวเลือกแทนการสะสม
Marty Wallace

และที่จริงแล้วสถานการณ์ในโค้ดหลักนั้นเกือบจะเป็นแบบนี้และฉันไม่สามารถเห็นการใช้คอลเลกชันได้
Marty Wallace

1
ฉันได้อัปเดตคำถามของฉันพร้อมข้อสงสัยเกี่ยวกับการใช้คอลเล็กชันแล้ว
Marty Wallace

1

ประการแรก - กลยุทธ์ในการกรองคอลเลกชันของคุณถูกต้อง เนื่องจากคอลเลกชันใน Magento สันหลังยาวโหลดคุณมีความสามารถในการสร้างวิธีการในโมเดลทรัพยากรของคุณเพื่อกำหนดข้อกำหนดของโหลดที่กำหนดเองของคุณให้แน่นขึ้น

หากไม่มีโค้ดตัวอย่างลองพิจารณาวิธีการหลอกต่อไปนี้ใน Resource Model ของคุณ:

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

    }
}

ฉันได้อัปเดตคำถามของฉันกับข้อกังวลของฉันเกี่ยวกับการใช้คอลเล็กชันสำหรับกรณีการใช้งานเฉพาะนี้ แต่ฉันไม่มีความรู้เพียงพอที่จะรู้ว่าทำไมคุณภาพเยี่ยมถึงทำแบบนี้ได้
Marty Wallace
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.