Tugasnya sepele. Saya perlu mendapatkan daftar produk untuk tampilan toko tertentu dengan katalog datar diaktifkan. Solusi yang paling jelas adalah sebagai berikut:
$collection = Mage::getResourceModel('catalog/product_collection')
->setStore($storeId);
Sebenarnya setStore()
metode ini tidak membuat perbedaan di sini karena ini disebut setelah _initSelect()
metode Mage_Catalog_Model_Resource_Product_Collection
yang mendapatkan nama tabel datar berdasarkan ID toko. Karena ID toko belum disetel, ID toko saat ini diperlukan.
Jadi solusi yang jelas adalah dengan menetapkan ID toko saat ini sebelum mendapatkan model.
Mage::app()->setCurrentStore($storeId);
$collection = Mage::getResourceModel('catalog/product_collection');
Itu akan berhasil. Tetapi hanya jika Anda perlu mendapatkan koleksi sekali. Jika Anda perlu mendapatkan koleksi di loop atau Anda hanya perlu dua koleksi back to back Anda tidak akan dapat mengatur toko khusus untuk mereka.
Alasannya adalah bahwa Mage_Catalog_Model_Resource_Product_Flat
kelas memiliki _storeId
properti itu sendiri dan dalam konstruktor itu diatur ke ID toko saat ini. Itu sebabnya ini akan ditetapkan pertama kali. Kemudian untuk beberapa alasan (surga tahu saya harap ada satu) di Mage_Eav_Model_Entity_Collection_Abstract::_init
setiap modul sumber daya diambil sebagai singleton. Jadi tidak ada konstruktor untuk panggilan kedua.
Ini semua terlihat sangat salah sehingga saya cukup yakin saya salah dan itu bukan bug Magento lainnya (atau dua). Semoga seseorang bisa menjelaskannya.
sumber
Jawaban:
Magento versi apa ini? Ini adalah hasil saya untuk Magento 1.9:
Katalog datar diaktifkan:
Katalog datar diindeks:
Beberapa data diatur dalam tampilan toko tertentu:
Kode yang digunakan:
Hasilnya seperti yang diharapkan:
edit:
Nevermind, katalog flat secara khusus dilarang untuk toko admin:
Investigasi ...
edit2:
Sepertinya Anda benar.
_initSelect
dipanggil sebelum kita dapat memodifikasi storeId yang digunakan untuk menghasilkan nama tabel.Tentu saja (jika kita tidak ingin melanjutkan rute penulisan ulang) kita dapat:
getSelect()
, lakukan reset dan atur yang baru dari ()$collection->getEntity()->setStoreId(123)
dan kemudian gunakan refleksi untuk menelepon_initSelect
lagi__construct
, menunda_initSelect
, dll).setCurrentStore
setiap kali kami membuat koleksi.Tapi ini semua terasa sangat berantakan ... Maaf, ini mungkin jawaban yang tidak memuaskan :-(
edit3:
Jadi demi menyediakan setidaknya sebuah jawaban:
Tolong jangan gunakan itu ;-)
sumber
product_collection
konstruktor menerima model sumber daya sebagai argumen. Jadi jika Anda membuatProduct_Resource_Flat
, atur id toko itu, tiru dan atur id toko lain, lalu berikan ke konstruktor koleksi, apakah itu bisa dilakukan?Jadi saya menganggap ini sebagai dua bug di Magento.
Yang pertama adalah fakta bahwa Anda tidak dapat menetapkan ID toko pada
catalog/product
koleksi. Dan yang kedua adalah Anda benar-benar tidak bisa mendapatkan model sumber daya sebagai non-tunggal.Jadi solusi bodoh adalah dengan instantiate model dua kali. Pertama kali ID toko dapat disetel dan instantiasi kedua akan menggunakannya:
sumber
Menariknya, tabel datar yang digunakan diatur sekali dan tidak pernah berubah yang berfungsi untuk EAV karena nama tabel tidak berubah tetapi tidak untuk flat karena nama tabel menyertakan ID toko. Solusinya adalah membuat helper yang akan menukar tabel di bagian FROM dari kueri. Berikut ini contoh pembantu seperti itu:
Maka Anda dapat menggunakannya hanya dengan:
Saya membayangkan ini tidak akan menimbulkan masalah untuk SQL karena Anda mengambil semua data dari satu tabel datar tapi karena itu adalah singleton toko yang terakhir digunakan akan digunakan di tempat lain.
Solusi alternatif adalah dengan membuat pengamat
catalog_product_collection_load_before
yang melakukan sesuatu seperti ini:Saya setuju bahwa orang-orang Magento harus memperbaikinya dalam
_beforeLoad()
metode ini.sumber
Mengapa tidak menggunakan filter biasa?
$collection->addAttributeToFilter('store_id', $store_id);
store_id diberikan sebagai kolom reguler di tabel * _eav_entity , jadi Anda juga bisa memfilternya. Bekerja untukku.
sumber
Jadilah karya saya solusi ini dengan core / app_emulation:
sumber