แนวทางปฏิบัติที่ดีที่สุดในการเข้าร่วมคุณสมบัติของผลิตภัณฑ์


11

product_idผมมีตารางที่กำหนดเองที่มีการอ้างอิงสินค้า ตอนนี้ฉันต้องการแสดงข้อมูลผลิตภัณฑ์ (sku, ชื่อ) ในตารางแบ็กเอนด์ของฉันแต่ฉันไม่แน่ใจว่าวิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?

การเดาที่ดีที่สุดของฉันSKUคือ:

$collection->join(
    'catalog/product',
    'product_id=`catalog/product`.entity_id',
    array('product_sku' => 'sku')
)

(รหัสจาก _prepareCollection() วิธีการในชั้นเรียนของฉันบล็อกตาราง)

แต่ชื่อผลิตภัณฑ์ล่ะ สามารถพบได้ใน catalog_product_entity_varchar ความเข้าใจของฉันคือการที่คุณค่อนข้างง่ายจะได้รับมันถ้ารุ่นทรัพยากรของคุณเองและคอลเลกชันจะขึ้นอยู่แล้วเพราะคุณสามารถใช้วิธีการเช่นMage_Eav_Model_Entity_Collection_Abstract joinAttributeแต่แบบจำลองของฉันขึ้นอยู่กับตารางอย่างง่ายและขยายจากMage_Core_Model_Resource_Db_Collection_Abstractและไม่มีjoinAttributeวิธีการที่ใช้ได้

ดังนั้นวิธีที่ดีที่สุดในการรับชื่อผลิตภัณฑ์ในกรณีนี้คืออะไร

ขอบคุณสำหรับเวลาและความช่วยเหลือ :-)

อัปเดต: เพื่อให้แม่นยำยิ่งขึ้นฉันกำลังพูดถึงรูปแบบและการรวบรวมทรัพยากรของฉัน มันตรงกับโต๊ะเรียบง่ายที่มีคุณสมบัติไม่กี่อย่างเช่น

entity_id    product_id    created_at    user_id

ความตั้งใจของฉันคือตารางในแบ็กเอนด์ที่ฉันแสดงสถิติบางอย่าง:

ProductSku    Count(ProductSku)    MAX(created_at)

เท่าที่ผมรู้ว่า approch _prepareCollection()ดีที่สุดในการทำเช่นนี้จะผ่านชั้นตารางบล็อกและวิธีการที่จะไปมี

วิธีการของฉันมีลักษณะเช่นนี้:

protected function _prepareCollection()
{
    // Get and set our collection for the grid
    $collection = Mage::getResourceModel($this->_getCollectionClass());
    $collection
        ->join(
            'catalog/product',
            'product_id=`catalog/product`.entity_id',
            array('product_sku' => 'sku')
            )
        ->addExpressionFieldToSelect('product_count', 'COUNT({{product_id}})', 'product_id')
        ->addExpressionFieldToSelect('newest', 'MAX({{created_at}})', array('created_at'=>'main_table.created_at'))
        ->getSelect()->group('product_id');
    $this->setCollection($collection);

    return parent::_prepareCollection();
}

สิ่งนี้ทำงานได้ดีสำหรับ sku (ซึ่งฉันอ้างถึงว่าเป็น product_sku ใน_prepareColums()วิธีการนี้ แต่joinฉันต้องใส่อะไรที่นี่เพื่อรับชื่อ (และเช่นผู้ผลิต)

ฉันทำอะไรผิดเพราะใช้ไม่ได้joinLeft()เหรอ

คำตอบ:


13

ในคลาสคอลเล็กชันของคุณ ( /Some/Module/Model/Mysql4 (or Resource)/YourModel/Collection.php) เพิ่มเมธอดนี้:

public function addProductData()
    {
        /** add particular attribute code to this array */
        $productAttributes = array('name', 'price', 'url_key');
        foreach ($productAttributes as $attributeCode) {
            $alias     = $attributeCode . '_table';
            $attribute = Mage::getSingleton('eav/config')
                ->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);

            /** Adding eav attribute value */
            $this->getSelect()->join(
                array($alias => $attribute->getBackendTable()),
                "main_table.product_id = $alias.entity_id AND $alias.attribute_id={$attribute->getId()}",
                array($attributeCode => 'value')
            );
            $this->_map['fields'][$attributeCode] = 'value';
        }
        /** adding catalog_product_entity table fields */
        $this->join(
            'catalog/product',
            'product_id=`catalog/product`.entity_id',
            array('sku' => 'sku', 'type_id' => 'type_id')
        );
        $this->_map['fields']['sku']     = 'sku';
        $this->_map['fields']['type_id'] = 'type_id';
        return $this;
    }

ในบล็อกกริดของคุณใช้ฟังก์ชันนี้:

 protected function _prepareCollection()
    {
        $collection = Mage::getModel('some/yourmodel')
            ->getCollection()->addProductData();
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

สิ่งนี้ดูมีแนวโน้ม แต่ก็ไม่ได้ผล คอลเลกชันของฉันยื่นออกมาจากและฉันได้รับข้อผิดพลาดMage_Core_Model_Resource_Db_Collection_Abstract Call to undefined method Mycompany_Module_Model_Resource_Mymodel_Collection::joinLeft()ฉันเดาว่าเป็นเพราะฉันไม่ได้ใช้ EAV Resource Model ใช่หรือไม่
Celldweller

ใช้เข้าร่วมแทนการเข้าร่วมซ้ายฉันแก้ไขคำตอบ
mageUz

DOH! ตอนนี้ฉันรู้สึกงี่เง่า! ;-) และฉันไม่รู้ว่าทำไมฉันลอง ขอบคุณมาก!
Celldweller

@ Celldweller คุณไม่จำเป็นต้องใช้$this->_map['fields']['sku'] = 'sku'หรือคล้ายกันในกรณีนี้ คุณต้องการมันก็ต่อเมื่อคุณมีชื่อฟิลด์ที่เหมือนกันหลายชื่อและจำเป็นต้องทำการแปลเพื่อป้องกันความขัดแย้ง มันเป็นเพียงการเพิ่มค่าใช้จ่ายสำหรับกรณีการใช้งานนี้ ในกรณีการใช้งานที่แตกต่างกันคุณอาจจะใช้$this->_map['fields']['my_sku'] = 'sku'แล้วคุณสามารถใช้กับการเก็บรวบรวมและ_prepareColumns: $this->addColumn('my_sku', array(…))มันจะช่วยให้คุณป้องกันความขัดแย้งสำหรับการกรองหรือคอลัมน์เรียงลำดับหากคุณมีสนามskuที่ใช้ในตารางฐานข้อมูลที่แตกต่างกันเป็นธรรมดาที่จะเก็บรวบรวม
ซิลแว็งเรย์

คำตอบที่ดี! มันอาจนำไปสู่ปัญหา "รายการที่มีรหัสเดียวกันนี้แล้ว" ง่าย ๆ$this->getSelect()->group('main_table.product_id');แก้ปัญหา แต่บางทีรหัสสามารถปรับให้เหมาะสมเพื่อให้รายการที่ซ้ำกันจะไม่ถูกสร้างขึ้นในตอนแรก?
Simon

4

สวัสดี Celldweller ฉันหวังว่าคุณจะทำได้ดี :-)

บางทีคุณผิดในคำอธิบายเกี่ยวกับคลาสMage_Core_Model_Resource_Db_Collection_Abstractคุณขยายคอลเลกชันทรัพยากรไม่ใช่โมเดลเนื่องจากคุณต้องไม่ขยายโมเดลด้วยคลาสคอลเล็กชันหากคุณต้องการเคารพโครงสร้างวีโอไอพี ฉันถูกไหม?

จากการแก้ไขของฉันฉันเห็นวิธีการที่แตกต่างกันขึ้นอยู่กับว่าคุณต้องการได้รับคุณลักษณะของชื่อผลิตภัณฑ์บ่อยแค่ไหน ไม่ว่าในกรณีใดฉันคิดว่าการสืบค้น sql ผ่าน Magento Framework เป็นวิธีที่ดีที่สุดและมีประสิทธิภาพ มันเร็วกว่าที่จะทำMage::getModel('catalog/product')->load(1234)->getName()สำหรับแต่ละรายการที่โหลด ดังนั้นในความเป็นจริงมันจะคล้ายกับรหัสที่คุณใช้สำหรับsku

รหัสไม่ผ่านการทดสอบ

คุณต้องการข้อมูลเหล่านั้นทุกครั้งที่มีการโหลดคอลเล็กชัน

คุณอาจจะอยู่ในชั้นเรียนคอลเลกชันของคุณตั้งเป็น_beforeLoadวิธีการรหัสเช่น

protected function _beforeLoad()
{
    $productName = Mage::getSingleton('eav/config')->getAttribute('catalog_product','name');

    $this->getSelect()
        ->join( array('product_attribute' => $productName->getBackendTable()),
            'main_table.product_id = product_attribute.entity_id',
            array())
        ->where("product_attribute.attribute_id = ?", $productName->getId());
    }

    return parent::_beforeLoad();
}

คุณต้องการข้อมูลเหล่านี้สำหรับตารางเท่านั้น

ในของ_prepareCollectionคุณคุณจะต้องเพิ่มวิธีการในคอลเลกชันของคุณด้วยรหัสเดียวกันกับที่ทำไว้ข้างต้นลงใน_beforeLoadนั้นคุณสามารถเตรียมคอลเลกชันโดยใช้วิธีนี้ อย่าใช้ทั้งสองอย่างฉันหมายถึงอย่าใช้รหัสเดียวกัน_beforeLoadและaddProductNameวิธีการร่วมกันใช้เพียงหนึ่งรหัสเท่านั้น นี่คือตัวอย่าง:

เป็นของคุณgrid.php:

protected function _prepareCollection()
{
    ...
    $collection->addProductName();
    $this->setCollection($collection);
    return parent::_prepareCollection();
}

เข้าสู่ Collection.php ของคุณ:

public function addProductName()
{
    $productName = Mage::getSingleton('eav/config')->getAttribute('catalog_product','name');

    $this->getSelect()
        -> join( array('product_attribute' => $productName->getBackendTable()),
            'main_table.product_id = product_attribute.entity_id',
            array())
        ->where("product_attribute.attribute_id = ?", $productName->getId());

    return $this;
}

ดีใจมากที่ได้อ่านคุณอีกครั้ง :-) ขอบคุณมาก แต่ฉันไม่สามารถใช้วิธี joinLeft () ฉันเดาว่านี่เป็นวิธีการเฉพาะรุ่นทรัพยากร EAV ใช่ไหม คุณพูดถูกฉันยังไม่ถูกต้องในคำถามเริ่มต้น ฉันจะแก้ไข :)
Celldweller

โอ้และ btw: แน่นอนว่าฉันไม่ต้องการทำผลิตภัณฑ์ -> load () ในสถานการณ์เช่นนี้ ยิงฉันถ้าฉันจะกล้า! ;-) เป้าหมายของฉันคือรวบรวมทุกอย่างไว้ในคอลเลกชันเดียวเพื่อให้สามารถทำการเรียงลำดับและกรองในตารางได้ ดูการปรับปรุงในโพสต์เริ่มต้นของฉันสำหรับรายละเอียดเพิ่มเติม
Celldweller

ดังนั้นแทนที่ joinLeft ด้วยการเข้าร่วม แต่คุณยอมรับคำตอบอื่น ๆ แล้วแม้ว่าฉันจะตอบถูกต้องและเป็นคนแรกที่ตอบ :-(
Sylvain Rayé

ใช่คุณถูก. ฉันมีความสุขมากจนในที่สุดมันก็ใช้งานได้ฉันไม่ได้คิดถึงมัน ฉันขอบคุณมากสำหรับคุณทั้งคู่ หวังว่าคุณจะยกโทษให้ฉันได้! ฉันเป็นหนี้คุณเบียร์
Celldweller

อ่าไม่ต้องกังวล เราพบคุณในเบอร์ลินด้วยความยินดี :-)
Sylvain Rayé

4

ฉันมีปัญหาเกือบเดียวกัน แต่ฉันไม่สามารถเพิ่มความคิดเห็นได้เพราะฉันไม่มีชื่อเสียง 50 ฉันใช้เวลาพยายามคิดว่าผิด (ฉันใช้รหัส Sylvain Rayé) การรวบรวมผลิตภัณฑ์ของฉันด้วยเหตุผลบางอย่างกรอง ดังนั้นฉันพบเหตุผล

หากคุณใช้เครื่องมือนำเข้า (magmi ฯลฯ ) เครื่องมือเหล่านี้มักจะไม่สร้างแอตทริบิวต์ที่ว่างเปล่าในครั้งเดียว ดังนั้นการใช้->where("product_attribute.attribute_id = ?", $productName->getId())ผลิตภัณฑ์ที่ไม่มีคุณสมบัตินี้จะหายไปจากการเลือก

วิธีที่ถูกต้องใช้joinLeftเช่นนั้น:

$productName = Mage::getSingleton('eav/config')->getAttribute('catalog_product','name');

$this->getSelect()
     ->joinLeft(array('product_attribute' => $productName->getBackendTable()),
        "main_table.product_id = product_attribute.entity_id AND
         product_attribute.attribute_id = {$productName->getId()}",
        array());

หวังว่านี่จะช่วยใครซักคน


-2

แสดงแอตทริบิวต์ที่กำหนดเองในตารางผลิตภัณฑ์

โปรดเขียนทับบล็อกนี้ Mage_Adminhtml_Block_Catalog_Product_Grid ในส่วนขยายและคัดลอกฟังก์ชั่น _prepareCollection และ _prepareColumns ของคุณลงในไฟล์บล็อกของส่วนขยาย

เพิ่มรหัสด้านล่างเพื่อเลือก attribuet ในฟังก์ชัน _prepareCollection ของตารางผลิตภัณฑ์ Mage_Adminhtml_Block_Catalog_Product_Grid ก่อน $ this-> setCollection ($ collection)

$attributeCode = 'qc_status';//here your attribute code
        $collection->joinAttribute($attributeCode, 'catalog_product/'.$attributeCode, 'entity_id', null, 'left');
        $collection->addAttributeToSelect($attributeCode);

แล้วด้านล่างรหัสสำหรับคอลัมน์ในฟังก์ชั่น _prepareColumns ของตาราง

$attributeCodeConfig ='qc_status';//Your attribute code...

        $attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_product', $attributeCodeConfig);

        $attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
        $attributeData = $attribute->getData();
        $frontEndLabel = $attributeData['frontend_label'];

        $attributeOptions = $attribute->getSource()->getAllOptions();
        $b = new Mage_Catalog_Model_Resource_Eav_Attribute();
        $attributeOptions2 = array();
        foreach ($attributeOptions as $value) {
            if(!empty($value['value'])) {
                $attributeOptions2[$value['value']] = $value['label'];
            }

        }


        if(count($attributeOptions2) > 0) {
            $this->addColumn($attributeCodeConfig,
                array(
                    'header'=> Mage::helper('catalog')->__($frontEndLabel),
                    'width' => '80px',
                    'index' => $attributeCodeConfig,
                    'type'  => 'options',
                    'options' => $attributeOptions2,

            ));
        } else {
            $this->addColumn($attributeCodeConfig,
                array(
                    'header'=> Mage::helper('catalog')->__($frontEndLabel),
                    'width' => '80px',
                    'index' => $attributeCodeConfig,

            ));
        }

เปลี่ยนไฟล์หลักไม่ใช่วิธีปฏิบัติที่ดี เหมือนกันสำหรับnew SomeModel()
sv3n

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