Mage_Catalog_Model_Resource_Product_Collection'da mağaza kimliği nasıl ayarlanır?


34

Görev önemsiz. Belirli bir mağaza görünümü için düz bir katalog etkinleştirilmiş ürünlerin listesini almam gerekiyor. En belirgin çözüm şudur:

$collection = Mage::getResourceModel('catalog/product_collection')
    ->setStore($storeId);

Aslında setStore()yöntem burada bir fark yaratmıyor, çünkü _initSelect()yöntemin Mage_Catalog_Model_Resource_Product_Collectionmağaza kimliğine dayanarak düz tablonun adını alan adı verildi. Mağaza kimliği henüz ayarlanmadığından, geçerli mağaza kimliğini alır.

Dolayısıyla, bariz geçici çözüm, bir model almadan önce mevcut bir mağaza kimliği belirlemek olacaktır.

Mage::app()->setCurrentStore($storeId);

$collection = Mage::getResourceModel('catalog/product_collection');

Çalışacak. Ancak sadece bir kez koleksiyon almanız gerekiyorsa. Döngüde bir koleksiyona ihtiyacınız varsa veya sadece arka arkaya iki koleksiyona ihtiyacınız varsa, onlar için belirli bir mağaza ayarlayamazsınız.

Bunun nedeni, Mage_Catalog_Model_Resource_Product_Flatsınıfın kendi _storeIdözelliğine sahip olması ve yapıcıda geçerli mağaza kimliğine ayarlanmış olmasıdır. Bu yüzden ilk kez ayarlanacak. Sonra bir nedenden ötürü (cennet bir tane olduğunu umuyorum) Mage_Eav_Model_Entity_Collection_Abstract::_inither bir kaynak modülünde tekil olarak alınır. Yani 2. çağrı için yapıcı yok.

Bunların hepsi o kadar yanlış görünüyor ki, yanlış olduğumdan ve başka bir Magento böceği (ya da iki) olmadığından eminim. Umarım birileri ışık tutabilir.


Bu size örnek verdiği için getResourceModel () işlevini kullanmak zorunda mısınız? getModel ('catalog / resource_product_collection') sadece işe yarayabilir.
Fooman'daki Kristof,

Hayır, kesinlikle aynı. Herhangi bir şekilde kaynak model singleton'u somutlaştırıyor.
user487772

Tim, lütfen cevap olarak ekle!
Fabian Blechschmidt,

@FabianBlechschmidt yapıldı.
user487772

Yanıtlar:


13

Bu Magento'nun versiyonu nedir? Bunlar Magento 1.9 için sonuçlarım:

Düz katalog etkin:

Düz katalog indekslendi:

Belirli bir mağaza görünümünde bazı veriler ayarlandı:

Kullanılan kod:

<?php

require_once 'app/Mage.php';

Mage::app('admin');

$collection = Mage::getResourceModel('catalog/product_collection')
    ->addAttributeToSelect('*')                                                                                                                                                                                                                                                 
    ->addFieldToFilter('entity_id', array('eq' => 231))
    ->setStore(2);

var_dump($collection->getFirstItem()->getName());

Sonuç beklendiği gibi:

string(18) "But I Am Le French"

Düzenle:

Nevermind, düz katalog yönetici mağaza için özel olarak yasaktır:

// Flat Data can be used only on frontend
if (Mage::app()->getStore()->isAdmin()) {
    return false;
}

İncelenmesi ...

edit2:

Haklı gibi görünüyorsun. _initSelectTablo ismini oluşturmak için kullanılan storeId'yi değiştirmeden önce çağrılır.

Elbette (yeniden yazma rotasına gitmek istemiyorsak) şunları yapabiliriz:

  • getSelect(), sıfırlayın ve () den yeni bir ayar yapın.
  • $collection->getEntity()->setStoreId(123)ve sonra _initSelecttekrar aramak için yansıma kullanın.
  • Sadece kendi kaynak modelimizi oluşturup düzden uzatarak doğru zamanda storeId eklemek için bir yol verin ( __construct, geciktirmek _initSelect, vb.).
  • setCurrentStorekoleksiyonu her yarattığımızda arayın .

Ancak bunların hepsi çok hack hissediyorum ... Üzgünüm, bu tatmin edici bir cevap olabilir :-(

Edit3:

Yani en azından bir cevap sağlama uğruna :

// Get collection and update store ID.
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->getEntity()->setStoreId(2);

// Reset the select.
$collection->getSelect()->reset();

// Update table name.
$reflectionMethod = new ReflectionMethod($collection, '_initSelect');
$reflectionMethod->setAccessible(true);
$reflectionMethod->invoke($collection);

// Do any other operations on the collection now.
$collection->addAttributeToSelect('*');

Lütfen kullanmayın ;-)


Sence bunun bir böcek olduğunu mu düşünüyorsun?
user487772

1
Kodun üzerine eğildim, ancak product_collectionyapıcısı bir kaynak modelini argüman olarak kabul ediyor. Öyleyse, eğer bir Product_Resource_Flatmağaza kimliği belirlerseniz, klonlayıp farklı bir mağaza kimliği belirlerseniz, koleksiyon yapıcısına iletirseniz, bu yapılabilir mi?
Melvyn

1
@Tim: Üzgünüm, sadece yorumunuzu gördüm. Evet bence bir böcek.
Daniel Sloof

cevap için yukarı, o 1.14.2.0 için çalışıyor
user4531

10

Bu yüzden bunların Magento'da iki böcek olduğunu düşünüyorum.

Birincisi, catalog/productkoleksiyon kimliğini koleksiyona koyamayacağınız gerçeğidir . İkincisi, kaynak modelini tekil olmayanlar olarak kesinlikle elde edemezsiniz.

Bu yüzden aptal geçici çözüm modeli iki kere başlatmak. Mağaza kimliği ilk kez ayarlanabiliyor ve ikinci örnekleme onu kullanacak:

Mage::getResourceModel('catalog/product_collection')->setStore($storeId);

$collection = Mage::getResourceModel('catalog/product_collection')

Mage :: getModel'deki set mağazamın neden ('katalog / kategori') -> getProductCollection () -> setStoreId () işe yaramadı. Bu arada teşekkürler
Nickool 29:14

3

İlginç bir şekilde, kullanılan düz masa bir kez ayarlanır ve hiçbir zaman değiştirilmez, çünkü EAV için çalışır; Bir geçici çözüm, sorgunun FROM kısmındaki tabloyu değiştirecek bir yardımcı yapmaktır. İşte böyle bir yardımcı örneği:

class My_Module_Helper_Data extends Mage_Core_Helper_Abstract
{
    public function getProductCollectionForStore($store)
    {
        $collection = Mage::getResourceModel('catalog/product_collection');

        // Change the store on the entity
        // This doesn't change it in the (already constructed) SQL query
        $collection->setStore($store);

        if (! $collection->isEnabledFlat()) {
            return $collection;
        }

        // Change the used table to the $store we want
        $select = $collection->getSelect();
        $from = $select->getPart('from');

        // Here, getFlatTableName() will pick up the store set above
        $from[$collection::MAIN_TABLE_ALIAS]['table'] =
        $from[$collection::MAIN_TABLE_ALIAS]['tableName'] = 
            $collection->getEntity()->getFlatTableName();

        $select->setPart('from', $from);
        return $collection;
    }
}

O zaman onu basitçe kullanabilirsiniz:

$collection = Mage::helper('my_module')->getProductCollectionForStore('somestore')
    ->addAttributeToSelect('name');

Tüm verileri tek bir düz masadan getirdiğiniz için bunun SQL için bir sorun yaratmayacağını hayal ediyorum, ancak bir singleton olduğu için en son kullanılan mağaza her yerde kullanılacaktı.

Alternatif çözüm, catalog_product_collection_load_beforebunun gibi bir şey yapan bir gözlemci yapmak olacaktır :

class My_Module_Model_Observer
{
    public function setCorrectFlatStore(Varien_Event_Observer $observer)
    {
        $collection = $observer->getCollection();
        if (! $collection->isEnabledFlat()) {
            return;
        }

        $select = $collection->getSelect();
        $from = $select->getPart('from');

        // If somebody called setStore() on the collection make sure
        // to update the used flat table
        $from[$collection::MAIN_TABLE_ALIAS]['table'] =
        $from[$collection::MAIN_TABLE_ALIAS]['tableName'] =
            $collection->getEntity()->getFlatTableName();

        $select->setPart('from', $from);
    }
}

Magento adamlarının bunu _beforeLoad()yöntemde düzeltmesi gerektiğine katılıyorum .


0

Neden normal bir filtre kullanmıyorsunuz?

$collection->addAttributeToFilter('store_id', $store_id);

store_id , * _eav_entity tablosunda normal bir sütun olarak verilir , böylece filtreleyebilirsiniz. Benim için çalıştı.


0

Benim işlerim çekirdek / app_emulation ile bu çözüm:

$storeId = 3;
$emulationModel = Mage::getModel('core/app_emulation');

// Emulate shop environment to disable using flat model and get collection for specific store
$emulationModel->startEnvironmentEmulation($storeId);
$products = Mage::getModel('catalog/product')->getCollection();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.