TL; DR , Wymagane jest, aby stan zapasów wyświetlać się na stronie z listą produktów kategorii przy jak najmniejszej liczbie dodatkowych zapytań / pamięci, mając na uwadze wydajność zgodną ze środowiskiem Magento.
Po przeczytaniu artykułu Vinai Kopp na temat wstępnego ładowania w celu zwiększenia skalowalności .
Jaki jest najlepszy sposób na uwzględnienie stanów magazynowych na stronach z listą produktów kategorii ( list.phtml ) przy jak najmniejszej liczbie dodatkowych zapytań / obciążeń ze względu na wydajność?
Mam świadomość kilku podejść:
Wydaje się, że afterLoad () działa dobrze zmedia_gallery
włączeniem bez dodatkowych zapytań, jednak nie udało mi się wdrożyć tego samego podejścia z zapasami.
$attributes = $_product->getTypeInstance(true)->getSetAttributes($_product);
$media_gallery = $attributes['media_gallery'];
$backend = $media_gallery->getBackend();
$backend->afterLoad($_product);
Bezpośredni SQL, aby zebrać wymagane dane równolegle do kolekcji, product_id
na przykład za pomocą klucza. Ale szukam więcej środków poprzez ramy.
Obecnie po prostu ładuję stock_item
obiekt poprzez:
$_product->load('stock_item')->getTotalQty();
Co działa, ale zauważam dodanie więcej zapytań, aby uzyskać podsumowanie zapasów magazynowych wszystkich produktów w kolekcji.
...
__EAV_LOAD_MODEL__ (Mage_Catalog_Model_Product, id: stock_item, attributes: NULL)
__EAV_LOAD_MODEL__ (Mage_Catalog_Model_Product, id: stock_item, attributes: NULL)
__EAV_LOAD_MODEL__ (Mage_Catalog_Model_Product, id: stock_item, attributes: NULL)
...
co dziwne, to działa. Magia dzieje się w Mage_Eav_Model_Entity_Abstract-> load ($ object, $ entityId, $ attribute). Jeśli $ atrybuty są puste, wywoła loadAllAttribute (obiekt $). Więc $ product-> load („bla”) załaduje wszystkie brakujące atrybuty, w tym „media_gallery” - William Tran 19 listopada 14 o 4:45
Dodaj potrzebne wartości do już załadowanej kolekcji.
Wydaje się, że najlepszym rozwiązaniem jest oczywiste proste podejście polegające na dodaniu potrzebnych danych do kolekcji produkcyjnej najwyższego poziomu w warstwie / filtrze.
Zauważyłem, że obserwator addInventoryDataToCollection () w Mage_CatalogInventory_Model_Observer brzmi, jakby to się udało, ale dodanie metody do niestandardowego modułu obserwatora nie wydaje się być kompatybilne.
<events>
<catalog_product_collection_load_after>
<observers>
<inventory>
<class>cataloginventory/observer</class>
<method>addInventoryDataToCollection</method>
</inventory>
</observers>
</catalog_product_collection_load_after>
</events>
Co skutkuje w:
Ostrzeżenie: Podano niepoprawny argument dla foreach () w /app/code/core/Mage/CatalogInventory/Model/Resource/Stock/Item/Collection.php w linii 71
źródło
Odpowiedzi:
Prawdziwym problemem tutaj nie jest wstępne ładowanie, to dokładność. Stosunkowo łatwo jest uzyskać zapasy dla kolekcji produktów:
Teraz dzięki dwóm zapytaniom masz wszystkie potrzebne informacje. Po prostu trudno je ze sobą powiązać, co można naprawić, używając tablicy asocjacyjnej
'product_id' => 'stock'
i pisząc getter. Ponadto addProductsFilter można zoptymalizować:Oszczędza to sprawdzania typu i klonowania tablicy.
Problemem jest teraz blokowanie pamięci podręcznej HTML. Ta strona kategorii musi zostać wyczyszczona, gdy jakikolwiek towar jest aktualizowany na produkcie w nim zawartym. O ile mi wiadomo, nie jest to standard, ponieważ tylko zmiana stanu magazynowego usuwa stronę kategorii zawierającą produkt (a dokładniej zmianę widoczności). Więc musisz obserwować przynajmniej,
cataloginventory_stock_item_before_save
a może kilka innych i wyczyścić pamięć podręczną html bloku (i pamięć podręczną FPC) dla tej strony kategorii.źródło
Widzę, że już zaakceptowałeś i bez wątpienia coś zaimplementowałeś, jednak chciałbym zwrócić uwagę na to, jak blisko byłeś,
addInventoryDataToCollection()
ale wygląda na to, że źle wpisałeś plik konfiguracyjny lub korzystamy z bardzo różnych wersji Magento. Moja kopiaCatalogInventory/etc/config.xml
ma inną wywoływaną metodęcatalog_product_collection_load_after
addInventoryDataToCollection()
jest wywoływany<sales_quote_item_collection_products_after_load>
Źródłem
addStockStatusToCollection()
jest:Możesz albo ustawić flagę
require_stock_items
w kolekcji, zanim się załaduje, prawdopodobnie nie jest to takie łatwe dla bloku za listą kategorii, albo możesz wywoływaćMage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection)
ręcznie w kolekcji, po jej załadowaniu.addItemsToProducts()
pobiera dla ciebie wszystkie produkty StockItems i dołącza je do kolekcji produktówźródło
Czy w ogóle używasz Lakieru lub FPC, czy planujesz w przyszłości?
Stwierdziliśmy, że przy wymaganej liczbie dziurkaczy / żądań ESI na listach produktów prawie nie warto było umieszczać buforowania na miejscu, dlatego zdecydowaliśmy się na inne podejście.
Wdrożyliśmy rozwiązanie na jednej stronie internetowej, która wykorzystuje żądanie AJAX do niestandardowego kontrolera w celu pobrania danych magazynowych produktów, a javascript obsługuje aktualizacje DOM. Dodatkowe żądanie danych magazynowych zajmuje ~ 100 ms, co wcale nie wpływa na ogólny (widoczny) czas ładowania strony. W połączeniu z gotowym FPC upuszczającym żądanie strony poniżej 100 ms masz jedną szybką witrynę o niskim koszcie wydajności do wyświetlania danych giełdowych na listach produktów.
Wszystko, co musisz zrobić, to dodać szablon productId do html opakowania każdego produktu, aby skrypt JavaScript wiedział, które dane giełdowe mają zastosowanie do każdego produktu.
Jeśli spojrzysz na dodatkowe techniki buforowania rzeczywistych danych o zapasach, możesz spaść to znacznie poniżej 100 ms, bez konieczności inicjowania Maga / trafiania do bazy danych na każde żądanie.
Przepraszamy, jeśli nie jest to zgodne z tym, czego szukasz, ale uznaliśmy, że jest to najlepsze podejście do skalowalności i wydajności w stosunku do naszych wymagań.
źródło