TL; DR , o requisito é que um nível de estoque do inventário seja exibido na página de listagem de produtos da categoria com menos consultas / memória adicionais, tendo em mente o desempenho que segue a estrutura do Magento.
Depois de ler o artigo de Vinai Kopp sobre pré - carregamento para escalabilidade .
Qual é a melhor maneira de incluir os níveis de estoque do inventário nas páginas de listagem de produtos da categoria ( list.phtml ) com o mínimo de consultas / cargas adicionais por questões de desempenho?
Estou ciente de algumas abordagens:
O afterLoad () parece funcionar bem com amedia_gallery
inclusão sem consultas adicionais, no entanto, não consegui implementar a mesma abordagem com o inventário.
$attributes = $_product->getTypeInstance(true)->getSetAttributes($_product);
$media_gallery = $attributes['media_gallery'];
$backend = $media_gallery->getBackend();
$backend->afterLoad($_product);
Direct SQL para reunir os dados necessários em paralelo à coleção com uma product_id
chave, por exemplo. Mas procurando mais meios através da estrutura.
Atualmente, estou simplesmente carregando o stock_item
objeto via:
$_product->load('stock_item')->getTotalQty();
O que funciona, mas noto a adição de mais consultas para obter o total do estoque de todos os produtos da coleção.
...
__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)
...
estranhamente, isso funciona. A mágica acontece em Mage_Eav_Model_Entity_Abstract-> load ($ object, $ entityId, $ attribute). Se $ attribute estiver vazio, ele chamará loadAllAttribute ($ object). Portanto, $ product-> load ('blah') carregará todos os atributos ausentes, incluindo 'media_gallery' #: 1967 William Tran
Adicione os valores necessários à coleção já carregada.
A abordagem simples e óbvia de adicionar os dados necessários à coleção de produção de nível superior na camada / filtro, parece ser a melhor abordagem.
Eu notei um observador addInventoryDataToCollection () em Mage_CatalogInventory_Model_Observer que parece que conseguiria isso, mas adicionar o método a um observador de módulos personalizados não parece ser compatível.
<events>
<catalog_product_collection_load_after>
<observers>
<inventory>
<class>cataloginventory/observer</class>
<method>addInventoryDataToCollection</method>
</inventory>
</observers>
</catalog_product_collection_load_after>
</events>
O que resulta em:
Aviso: argumento inválido fornecido para foreach () em /app/code/core/Mage/CatalogInventory/Model/Resource/Stock/Item/Collection.php na linha 71
fonte
Respostas:
O problema real aqui não é o pré-carregamento, é a precisão. É relativamente fácil obter o valor do estoque de uma coleção de produtos:
Agora, com duas consultas, você tem todas as informações necessárias. Eles são difíceis de se relacionar, o que pode ser corrigido usando uma matriz associativa
'product_id' => 'stock'
e escrevendo um getter. Além disso, o addProductsFilter pode ser otimizado:Isso economiza a verificação de tipo e a clonagem de matriz.
O problema agora é bloquear o cache HTML. Essa página de categoria precisa ser limpa quando qualquer estoque for atualizado em um produto contido nela. Até onde eu sei, isso não é padrão, pois apenas uma alteração no status do estoque elimina uma página de categoria que contém um produto (ou, mais precisamente, uma alteração na visibilidade). Portanto, você precisará observar pelo menos,
cataloginventory_stock_item_before_save
talvez alguns outros, e limpar o cache html do bloco (e o cache do FPC) para essa página de categoria.fonte
Vejo que você já aceitou e sem dúvida implementou algo até agora, no entanto, gostaria de salientar o quão perto você estava,
addInventoryDataToCollection()
mas parece que você citou incorretamente o arquivo de configuração ou estamos usando versões muito diferentes do magento. Minha cópiaCatalogInventory/etc/config.xml
tem um método diferente chamadocatalog_product_collection_load_after
addInventoryDataToCollection()
é chamado<sales_quote_item_collection_products_after_load>
A fonte para
addStockStatusToCollection()
é:Você pode definir o sinalizador
require_stock_items
na coleção antes de ser carregado, provavelmente não é tão fácil para o bloco atrás da lista de categorias ou pode chamarMage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection)
manualmente a coleção, depois que ela já estiver carregada.addItemsToProducts()
obtém todos os StockItems para você e os anexa à sua ProductCollectionfonte
Você está usando verniz ou FPC, ou planeja no futuro?
Descobrimos que, com a quantidade de solicitações de perfurações / ESI exigidas nas listagens de produtos, quase não valia a pena ter o cache no local, então optamos por uma abordagem diferente.
Implementamos uma solução em um site que usa uma solicitação AJAX para um controlador personalizado para recuperar os dados de estoque dos produtos e o javascript manipula as atualizações do DOM. A solicitação adicional para os dados de estoque leva aproximadamente 100 ms, o que não afeta o tempo total de carregamento da página (visível). Além disso, com o FPC inicializado, a solicitação da página cai para menos de 100 ms, você tem um site rápido com sobrecarga de baixo desempenho para exibir dados de estoque nas listas de produtos.
Tudo o que você precisa fazer de modelo é adicionar o productId a cada wrapper de produtos html, para que seu javascript saiba quais dados de estoque serão aplicados a cada produto.
Se você observar técnicas de armazenamento em cache adicionais para os dados de estoque reais, poderá cair muito abaixo de 100ms por não precisar iniciar o Mage / acessar o banco de dados em cada solicitação.
Desculpe se isso não coincide com o que você está procurando, mas achamos que é a melhor abordagem para escalabilidade e desempenho em relação aos nossos requisitos.
fonte