Praktik terbaik untuk bergabung dengan atribut produk

11

Saya memiliki tabel khusus dengan referensi produk product_id. Sekarang saya ingin menunjukkan informasi produk (sku, nama) di grid backend saya , tetapi saya tidak yakin apa praktik terbaik untuk melakukan ini?

Tebakan terbaik saya SKUadalah sebagai berikut:

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

(kode dari _prepareCollection() metode di kelas blok kotak saya)

Tapi bagaimana dengan nama produk? Itu dapat ditemukan di catalog_product_entity_varchar. Pemahaman saya adalah bahwa Anda dapat dengan mudah mendapatkannya jika model sumber daya Anda sendiri dan koleksi didasarkan Mage_Eav_Model_Entity_Collection_Abstractkarena Anda dapat menggunakan metode seperti joinAttribute. Tetapi model saya didasarkan pada tabel sederhana dan memanjang dari Mage_Core_Model_Resource_Db_Collection_Abstractdan tidak ada joinAttributemetode yang tersedia.

Jadi apa cara terbaik untuk mendapatkan nama produk dalam kasus ini?

Terima kasih atas waktu dan bantuan Anda :-)

Pembaruan: Untuk lebih tepatnya, saya berbicara tentang model dan koleksi sumber daya saya. Ini cocok dengan tabel datar sederhana dengan hanya beberapa atribut seperti

entity_id    product_id    created_at    user_id

Niat saya adalah menyambungkan di backend tempat saya menampilkan beberapa statistik:

ProductSku    Count(ProductSku)    MAX(created_at)

Sejauh yang saya tahu, pendekatan terbaik untuk melakukan ini, adalah melalui kelas kotak blok dan metode untuk pergi adalah _prepareCollection().

Metode saya terlihat seperti ini:

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();
}

Ini berfungsi dengan baik untuk sku (yang saya sebut sebagai product_sku dalam _prepareColums()metode. Tapi apa yang joinharus saya masukkan di sini untuk mendapatkan nama (dan misalnya produsen)?

Apakah saya melakukan sesuatu yang salah karena saya tidak dapat menggunakan joinLeft()?

Celldweller
sumber

Jawaban:

13

Di kelas koleksi Anda ( /Some/Module/Model/Mysql4 (or Resource)/YourModel/Collection.php) tambahkan metode ini:

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

Di blok kotak Anda gunakan fungsi ini:

 protected function _prepareCollection()
    {
        $collection = Mage::getModel('some/yourmodel')
            ->getCollection()->addProductData();
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }
mageUz
sumber
Ini terlihat menjanjikan, tetapi sayangnya tidak berhasil. Koleksi saya memanjang dari Mage_Core_Model_Resource_Db_Collection_Abstractdan saya mendapatkan kesalahan Call to undefined method Mycompany_Module_Model_Resource_Mymodel_Collection::joinLeft(). Saya kira ini karena saya tidak menggunakan Model Sumber Daya EAV?
Celldweller
Gunakan bergabung, bukan joinLeft, saya mengedit jawabannya
mageUz
lakukan! Saya merasa bodoh sekarang! ;-) Dan saya tidak tahu mengapa saya mencobanya. Terima kasih banyak!
Celldweller
@Celldweller, Anda bahkan tidak perlu menggunakan $this->_map['fields']['sku'] = 'sku'atau serupa dalam hal ini. Anda memerlukannya hanya jika Anda memiliki beberapa nama bidang yang identik dan perlu melakukan terjemahan untuk mencegah konflik. Itu hanya menambahkan overhead untuk use case ini. Dalam kasus penggunaan yang berbeda, Anda dapat menggunakan $this->_map['fields']['my_sku'] = 'sku'maka Anda dapat menggunakan dengan koleksi dan _prepareColumns: $this->addColumn('my_sku', array(…)), itu akan membantu Anda untuk mencegah konflik untuk penyaringan atau kolom menyortir jika Anda telah lapangan skudigunakan dalam berbagai tabel DB umum untuk koleksi
Sylvain Raye
Jawaban bagus! Ini dapat menyebabkan masalah "item dengan ID yang sama sudah ada". Sederhana $this->getSelect()->group('main_table.product_id');memecahkan masalah, tetapi mungkin kode dapat dioptimalkan, sehingga duplikat tidak dibuat di tempat pertama?
Simon
4

Hai Celldweller Saya harap Anda baik-baik saja :-)

Mungkin Anda salah dalam menjelaskan tentang kelas Mage_Core_Model_Resource_Db_Collection_Abstract, Anda memperluas koleksi sumber daya bukan model karena Anda tidak harus memperluas model dengan kelas koleksi jika Anda ingin menghormati struktur Magento. Apakah saya benar?

Berdasarkan koreksi saya, saya melihat berbagai jenis pendekatan, tergantung pada seberapa sering Anda ingin mendapatkan atribut nama produk. Bagaimanapun, saya pikir untuk melakukan kueri sql melalui Magento Framework adalah cara terbaik dan efisien. Ini lebih cepat daripada melakukan Mage::getModel('catalog/product')->load(1234)->getName()untuk setiap item yang dimuat. Jadi sebenarnya itu akan sangat mirip dengan kode yang Anda gunakan untuksku

KODE TIDAK DIUJI

Anda ingin informasi itu setiap kali koleksi dimuat

Anda mungkin dalam kelas koleksi Anda menetapkan _beforeLoadmetode seperti kode:

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();
}

Anda ingin HANYA informasi itu untuk grid

Di Anda _prepareCollection, Anda harus menambahkan metode dalam koleksi Anda dengan kode yang sama seperti yang dilakukan di atas ke dalam _beforeLoadmaka Anda dapat menyiapkan koleksi dengan menggunakan metode ini. Jangan gunakan keduanya, maksud saya jangan gunakan bersama-sama kode _beforeLoaddan addProductNamemetode yang sama, gunakan hanya satu saja. Berikut ini contohnya:

Ke dalam Anda grid.php:

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

Ke dalam Collection.php Anda:

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;
}
Sylvain Rayé
sumber
Senang membaca Anda lagi :-) Terima kasih banyak tetapi saya tidak bisa menggunakan metode joinLeft (). Saya kira ini hanya metode sumber daya model EAV? Anda benar, saya tidak aman dalam pertanyaan awal saya. Saya akan mengeditnya :)
Celldweller
Oh dan btw: Tentu saja saya tidak ingin melakukan product-> load () dalam situasi seperti itu. Tembak aku jika aku berani! ;-) Tujuan saya adalah untuk memiliki semuanya dalam satu koleksi agar dapat melakukan penyortiran dan penyaringan di grid. Lihat pembaruan di posting awal saya untuk rincian lebih lanjut.
Celldweller
Jadi gantikan joinLeft dengan bergabung tetapi Anda sudah menerima jawaban yang lain meskipun saya menjawab dengan benar dan yang pertama menjawab :-(
Sylvain Rayé
Ya kamu benar. Saya sangat senang akhirnya berhasil, saya tidak memikirkannya. Saya sangat berterima kasih kepada Anda berdua. Semoga kamu bisa memaafkan aku! Aku berhutang bir padamu.
Celldweller
ahah jangan khawatir. Kami bertemu dengan Anda di Berlin dengan senang hati :-)
Sylvain Rayé
4

Saya memiliki masalah yang hampir sama, tetapi saya tidak dapat menambahkan komentar, karena saya tidak memiliki 50 reputasi. Saya menghabiskan banyak waktu untuk mencari tahu apa yang salah (saya menggunakan kode Sylvain Rayé). Koleksi produk saya karena alasan tertentu difilter. Jadi saya menemukan alasannya.

Jika Anda menggunakan beberapa alat impor (magmi, dll), mereka sering tidak membuat atribut kosong sekaligus. Karenanya menggunakan ->where("product_attribute.attribute_id = ?", $productName->getId())produk yang tidak memiliki atribut ini, akan hilang dari seleksi.

Cara yang benar menggunakan joinLeftseperti itu:

$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());

Semoga ini bisa membantu seseorang.

spiil
sumber
-2

Tampilkan atribut khusus pada kisi produk.

Timpa blok ini Mage_Adminhtml_Block_Catalog_Product_Grid di ekstensi Anda dan salin fungsi _prepareCollection dan _prepareColumns ke dalam file blok ekstensi Anda.

Tambahkan kode di bawah ini untuk memilih attribuet di fungsi _prepareCollection dari kisi produk Mage_Adminhtml_Block_Catalog_Product_Grid sebelum $ this-> setCollection ($ collection) line.

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

Dan kemudian di bawah ini kode untuk kolom dalam fungsi _prepareColumns dari kisi.

$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,

            ));
        }
Savoo
sumber
Mengubah file inti bukan praktik yang baik. Sama untuknew SomeModel()
sv3n
kita tidak perlu mengubah file inti. Kita dapat menimpa blok itu (Mage_Adminhtml_Block_Catalog_Product_Grid) untuk mencapai fungsionalitas kita
Savoo