Zadanie jest trywialne. Potrzebuję uzyskać listę produktów dla konkretnego widoku sklepu z włączonym płaskim katalogiem. Najbardziej oczywistym rozwiązaniem jest:
$collection = Mage::getResourceModel('catalog/product_collection')
->setStore($storeId);
W rzeczywistości setStore()
metoda nie robi tu żadnej różnicy, ponieważ jest wywoływana po _initSelect()
metodzie, Mage_Catalog_Model_Resource_Product_Collection
która otrzymuje nazwę płaskiego stołu na podstawie identyfikatora sklepu. Ponieważ identyfikator sklepu nie jest jeszcze ustawiony, pobiera bieżący identyfikator sklepu.
Oczywistym obejściem byłoby ustawienie bieżącego identyfikatora sklepu przed uzyskaniem modelu.
Mage::app()->setCurrentStore($storeId);
$collection = Mage::getResourceModel('catalog/product_collection');
To będzie działać. Ale tylko wtedy, gdy musisz raz zdobyć kolekcję. Jeśli potrzebujesz uzyskać kolekcję w pętli lub potrzebujesz tylko dwóch kolekcji z powrotem do tyłu, nie będziesz w stanie ustawić dla nich konkretnego sklepu.
Powodem jest to, że Mage_Catalog_Model_Resource_Product_Flat
klasa ma swoją _storeId
własność, aw konstruktorze jest ustawiona na bieżący identyfikator sklepu. Dlatego zostanie ustawiony po raz pierwszy. Następnie z jakiegoś powodu (niebo wie, mam nadzieję, że istnieje) w Mage_Eav_Model_Entity_Collection_Abstract::_init
każdym module zasobów jest pobierany jako singleton. Więc nie ma konstruktora dla drugiego połączenia.
To wszystko wygląda tak źle, że jestem prawie pewien, że się mylę i nie jest to kolejny błąd Magento (lub dwa). Mam nadzieję, że ktoś może rzucić na to światło.
źródło
Odpowiedzi:
Jaka to wersja Magento? Oto moje wyniki dla Magento 1.9:
Włączono płaski katalog:
Katalog płaski jest indeksowany:
Niektóre dane w określonym widoku sklepu:
Zastosowany kod:
Wynik jest zgodny z oczekiwaniami:
edytować:
Nieważne, płaski katalog jest szczególnie zabroniony dla sklepu administracyjnego:
Badanie ...
edycja2:
Wygląda na to, że masz rację.
_initSelect
jest wywoływany, zanim będziemy mogli zmodyfikować storeId, który jest używany do generowania nazwy tabeli.Oczywiście (jeśli nie chcemy skorzystać z przepisanej trasy) możemy:
getSelect()
, zresetuj i ustaw nowy from ()$collection->getEntity()->setStoreId(123)
a następnie użyj refleksji, aby_initSelect
ponownie zadzwonić__construct
opóźnienie_initSelect
itp.).setCurrentStore
za każdym razem, gdy tworzymy kolekcję.Ale wszyscy czują się bardzo hacky ... Niestety, może to być niezadowalająca odpowiedź :-(
edycja3:
Tak przez wzgląd na zapewnienie co najmniej o odpowiedź:
Nie używaj tego ;-)
źródło
product_collection
konstruktor akceptuje model zasobów jako argument. Więc jeśli utworzyszProduct_Resource_Flat
, ustawisz identyfikator sklepu, sklonujesz go i ustawisz inny identyfikator sklepu, a następnie przekażesz go konstruktorowi kolekcji, czy byłoby to wykonalne?Uważam więc, że są to dwa błędy w Magento.
Pierwszym z nich jest fakt, że nie można ustawić identyfikatora sklepu na
catalog/product
kolekcji. Po drugie, absolutnie nie można uzyskać modelu zasobów jako nie singletonu.Głupie obejście polega na dwukrotnym utworzeniu modelu. Po raz pierwszy można ustawić identyfikator sklepu i użyje go druga instancja:
źródło
Co ciekawe, używana płaska tabela jest ustawiana raz i nigdy się nie zmienia, co działa dla EAV, ponieważ nazwa tabeli się nie zmienia, ale nie dla płaskiej, ponieważ nazwa tabeli zawiera identyfikator sklepu. Obejściem byłoby utworzenie pomocnika, który zamieniłby tabelę w części FROM zapytania. Oto przykład takiego pomocnika:
Następnie możesz użyć go po prostu z:
Wyobrażam sobie, że nie spowodowałoby to problemów dla SQL, ponieważ pobierasz wszystkie dane z pojedynczej płaskiej tabeli, ale ponieważ jest to singleton, ostatnio używany sklep byłby używany wszędzie indziej.
Alternatywnym rozwiązaniem byłoby stworzenie obserwatora,
catalog_product_collection_load_before
który zrobiłby coś takiego:Zgadzam się, że faceci Magento powinni to naprawić w
_beforeLoad()
metodzie.źródło
Dlaczego nie użyć zwykłego filtra?
$collection->addAttributeToFilter('store_id', $store_id);
store_id jest podany jako zwykła kolumna w tabeli * _eav_entity , więc możesz go również filtrować. Pracował dla mnie.
źródło
Bądź moim dziełem to rozwiązanie z core / app_emulation:
źródło