La tarea es trivial. Necesito obtener una lista de productos para ver una tienda en particular con un catálogo plano habilitado. La solución más obvia es la siguiente:
$collection = Mage::getResourceModel('catalog/product_collection')
->setStore($storeId);
De hecho, el setStore()
método no hace ninguna diferencia aquí porque se llama después de que el _initSelect()
método Mage_Catalog_Model_Resource_Product_Collection
obtiene el nombre de la tabla plana según la ID de la tienda. Como la ID de la tienda aún no está configurada, toma la ID de la tienda actual.
Por lo tanto, la solución obvia sería establecer una ID de tienda actual antes de obtener un modelo.
Mage::app()->setCurrentStore($storeId);
$collection = Mage::getResourceModel('catalog/product_collection');
Funcionará. Pero solo si necesita obtener una colección una vez. Si necesita obtener una colección en el ciclo o simplemente necesita dos colecciones consecutivas, no podrá establecer una tienda específica para ellas.
La razón es que la Mage_Catalog_Model_Resource_Product_Flat
clase tiene su propia _storeId
propiedad y en el constructor se establece en el ID de la tienda actual. Es por eso que se establecerá la primera vez. Entonces, por alguna razón (Dios sabe que espero que haya uno) en Mage_Eav_Model_Entity_Collection_Abstract::_init
cada módulo de recursos se obtiene como un singleton. Entonces no hay constructor para la 2da llamada.
Todo esto se ve tan mal que estoy bastante seguro de que estoy equivocado y no es otro error de Magento (o dos). Espero que alguien pueda arrojar una luz sobre ello.
fuente
Respuestas:
¿Qué versión de Magento es esta? Estos son mis resultados para Magento 1.9:
Catálogo plano habilitado:
El catálogo plano está indexado:
Algunos conjuntos de datos en una vista de tienda específica:
Código usado:
El resultado es el esperado:
editar:
No importa, el catálogo plano está específicamente prohibido para la tienda de administración:
Investigando ...
edit2:
Parece que tienes razón.
_initSelect
se llama antes de que podamos modificar el storeId que se usa para generar el nombre de la tabla.Por supuesto (si no queremos seguir la ruta de reescritura) podemos:
getSelect()
, reiniciar y establecer un nuevo desde ()$collection->getEntity()->setStoreId(123)
y luego usa la reflexión para_initSelect
volver a llamar__construct
, retrasos_initSelect
, etc.).setCurrentStore
cada vez que creamos la colección.Pero todo esto se siente muy hacky ... Lo siento, esta puede ser una respuesta insatisfactoria :-(
edit3:
Entonces, en aras de proporcionar al menos una respuesta:
Por favor no uses eso ;-)
fuente
product_collection
el constructor acepta un modelo de recurso como argumento. Entonces, si crea unProduct_Resource_Flat
, establezca su id de tienda, clónelo y establezca un id de tienda diferente, luego páselo al constructor de la colección, ¿sería factible?Así que considero que estos son dos errores en Magento.
El primero es el hecho de que no puede establecer la identificación de la tienda en la
catalog/product
colección. Y el segundo es que absolutamente no puede obtener el modelo de recurso como no singleton.Entonces, una solución estúpida es instanciar el modelo dos veces. La primera vez que se puede configurar el ID de la tienda y la segunda instancia lo usará:
fuente
Curiosamente, la tabla plana usada se establece una vez y nunca cambia, lo que funciona para EAV ya que el nombre de la tabla no cambia, pero no para plana, ya que el nombre de la tabla incluye el ID de la tienda. Una solución alternativa sería hacer un ayudante que intercambie la tabla en la parte DE de la consulta. Aquí hay un ejemplo de tal ayuda:
Entonces puedes usarlo simplemente con:
Me imagino que esto no causaría problemas para el SQL ya que está obteniendo todos los datos de una sola tabla plana, pero como es un singleton, la última tienda utilizada se usaría en cualquier otro lugar.
Una solución alternativa sería hacer un observador
catalog_product_collection_load_before
que haga algo como esto:Estoy de acuerdo en que los chicos de Magento deberían arreglar esto en el
_beforeLoad()
método.fuente
¿Por qué no usar un filtro habitual?
$collection->addAttributeToFilter('store_id', $store_id);
store_id se proporciona como una columna regular en la tabla * _eav_entity , por lo que también puede filtrar por ella. Trabajó para mi.
fuente
Be my works esta solución con core / app_emulation:
fuente