A tarefa é trivial. Preciso obter uma lista de produtos para uma visualização específica da loja com um catálogo plano ativado. A solução mais óbvia é a seguinte:
$collection = Mage::getResourceModel('catalog/product_collection')
->setStore($storeId);
De fato, o setStore()
método não faz nenhuma diferença aqui porque é chamado após o _initSelect()
método Mage_Catalog_Model_Resource_Product_Collection
que obtém o nome da tabela simples com base no ID da loja. Como o ID da loja ainda não está definido, ele aceita o ID da loja atual.
Portanto, a solução óbvia seria definir um ID de loja atual antes de obter um modelo.
Mage::app()->setCurrentStore($storeId);
$collection = Mage::getResourceModel('catalog/product_collection');
Vai funcionar. Mas apenas se você precisar obter uma coleção uma vez. Se você precisar obter uma coleção no loop ou precisar apenas de duas coleções consecutivas, não poderá definir um armazenamento específico para elas.
O motivo é que a Mage_Catalog_Model_Resource_Product_Flat
classe tem sua própria _storeId
propriedade e, no construtor, é definida como o ID da loja atual. É por isso que será definido pela primeira vez. Então, por alguma razão (Deus sabe que espero que exista), em Mage_Eav_Model_Entity_Collection_Abstract::_init
cada módulo de recurso é buscado como um singleton. Portanto, nenhum construtor para a segunda chamada.
Tudo isso parece tão errado que eu tenho certeza que estou errado e não é outro bug do Magento (ou dois). Espero que alguém possa esclarecer isso.
fonte
Respostas:
Que versão do Magento é essa? Estes são os meus resultados para o Magento 1.9:
Catálogo plano ativado:
O catálogo plano é indexado:
Alguns conjuntos de dados em uma visualização de loja específica:
Código usado:
O resultado é o esperado:
editar:
Não importa, o catálogo plano é especificamente proibido para o repositório de administradores:
Investigando ...
edit2:
Parece que você está certo.
_initSelect
é chamado antes que possamos modificar o storeId que é usado para gerar o nome da tabela.Obviamente (se não quisermos seguir a rota de reescrita), podemos:
getSelect()
, redefina e defina um novo de ()$collection->getEntity()->setStoreId(123)
e depois use a reflexão para ligar_initSelect
novamente__construct
, atrasar_initSelect
, etc.).setCurrentStore
sempre que criarmos a coleção.Mas tudo isso parece muito hacky ... Desculpe, isso pode ser uma resposta insatisfatória :-(
edit3:
Portanto, para fornecer pelo menos uma resposta:
Por favor, não use isso ;-)
fonte
product_collection
o construtor aceita um modelo de recurso como argumento. Portanto, se você criar umProduct_Resource_Flat
, defina seu ID de loja, clone-o e defina um ID de loja diferente e passe-o para o construtor de coleções, isso seria possível?Então eu considero esses dois bugs no Magento.
O primeiro é o fato de que você não pode definir o ID da loja na
catalog/product
coleção. E a segunda é que você absolutamente não pode obter o modelo de recurso como não singleton.Uma solução tão estúpida é instanciar o modelo duas vezes. A primeira vez que o ID da loja pode ser definido e a segunda instanciação o utilizará:
fonte
Curiosamente, a tabela simples usada é configurada uma vez e nunca é alterada, o que funciona para o EAV, pois o nome da tabela não muda, mas não para o flat, pois o nome da tabela inclui o ID da loja. Uma solução alternativa seria criar um auxiliar que trocasse a tabela na parte FROM da consulta. Aqui está um exemplo de tal ajudante:
Então você pode usá-lo simplesmente com:
Eu imagino que isso não causaria problemas para o SQL, pois você está buscando todos os dados de uma única tabela plana, mas como é um singleton, o último armazenamento usado seria usado em qualquer outro lugar.
Uma solução alternativa seria criar um observador
catalog_product_collection_load_before
que faça algo assim:Concordo que os caras do Magento devem corrigir isso no
_beforeLoad()
método.fonte
Por que não usar um filtro comum?
$collection->addAttributeToFilter('store_id', $store_id);
store_id é fornecido como uma coluna regular na tabela * _eav_entity , para que você também possa filtrar por ela. Trabalhou para mim.
fonte
Seja meus trabalhos esta solução com core / app_emulation:
fonte