La tâche est triviale. Je dois obtenir la liste des produits pour une vue de magasin particulière avec un catalogue à plat activé. La solution la plus évidente est la suivante:
$collection = Mage::getResourceModel('catalog/product_collection')
->setStore($storeId);
En fait, setStore()
méthode ne fait aucune différence ici car elle est appelée après la _initSelect()
méthode Mage_Catalog_Model_Resource_Product_Collection
qui obtient le nom de la table à plat en fonction de l'ID de magasin. L'ID de magasin n'étant pas encore défini, il prend l'identifiant de magasin actuel.
La solution évidente serait donc de définir un ID de magasin actuel avant d’obtenir un modèle.
Mage::app()->setCurrentStore($storeId);
$collection = Mage::getResourceModel('catalog/product_collection');
Ça va marcher. Mais seulement si vous devez obtenir une collection une fois. Si vous avez besoin d'une collection dans la boucle ou si vous avez juste besoin de deux collections consécutives, vous ne pourrez pas définir de magasin spécifique pour elles.
La raison en est que cette Mage_Catalog_Model_Resource_Product_Flat
classe a sa propre _storeId
propriété et que, dans le constructeur, elle est définie sur l'ID de magasin actuel. C'est pourquoi il sera réglé pour la première fois. Ensuite, pour une raison quelconque (Dieu sait que j'espère qu'il y en a un), Mage_Eav_Model_Entity_Collection_Abstract::_init
chaque module de ressource est récupéré en tant que singleton. Donc, pas de constructeur pour le 2e appel.
Tout cela a l'air tellement faux que je suis presque sûr que je me trompe et que ce n'est pas un autre bogue de Magento (ou deux). J'espère que quelqu'un pourra nous éclairer.
la source
Réponses:
De quelle version de Magento s'agit-il? Voici mes résultats pour Magento 1.9:
Catalogue plat activé:
Le catalogue plat est indexé:
Certaines données définies dans une vue de magasin spécifique:
Code utilisé:
Le résultat est comme prévu:
modifier:
Nevermind, le catalogue plat est spécifiquement interdit pour admin store:
Enquête ...
edit2:
On dirait que tu as raison.
_initSelect
est appelé avant que nous puissions modifier le storeId qui est utilisé pour générer le nom de la table.Bien sûr (si nous ne voulons pas emprunter la voie de la réécriture), nous pouvons:
getSelect()
, réinitialiser et définir un nouveau élément from ()$collection->getEntity()->setStoreId(123)
puis utiliser la réflexion pour appeler à_initSelect
nouveau__construct
en retardant_initSelect
, etc.).setCurrentStore
chaque fois que nous créons la collection.Mais tous se sentent très mal en point ... Désolé, cela peut être une réponse peu satisfaisante :-(
edit3:
Donc, dans le but de fournir au moins une réponse:
S'il vous plaît, n'utilisez pas ça ;-)
la source
product_collection
le constructeur accepte un modèle de ressource comme argument. Ainsi, si vous créez unProduct_Resource_Flat
, définissez son identifiant de magasin, le clonez et définissez un autre identifiant de magasin, puis transmettez-le au constructeur de la collection, est-ce faisable?Je considère donc qu'il s'agit de deux bogues dans Magento.
Le premier est le fait que vous ne pouvez pas définir d'ID de magasin lors de la
catalog/product
collecte. Et le second est que vous ne pouvez absolument pas obtenir un modèle de ressource non singleton.La solution de rechange si stupide consiste à instancier deux fois le modèle. La première fois que l'ID de magasin peut être défini et que la deuxième instanciation l'utilisera:
la source
Fait intéressant, la table plate utilisée est définie une fois et n’a jamais changé, ce qui fonctionne pour EAV puisque le nom de la table ne change pas, mais pas pour plate car le nom de la table inclut l’ID de magasin. Une solution de contournement consisterait à créer un assistant qui permuterait la table dans la partie FROM de la requête. Voici un exemple d'un tel assistant:
Ensuite, vous pouvez l'utiliser simplement avec:
J'imagine que cela ne poserait aucun problème pour le SQL puisque vous récupérez toutes les données d'une seule table plate, mais comme il s'agit d'un singleton, le dernier magasin utilisé sera utilisé partout ailleurs.
La solution alternative serait de faire un observateur sur
catalog_product_collection_load_before
lequel fait quelque chose comme ceci:Je suis d'accord que les gars de Magento devraient résoudre ce problème dans la
_beforeLoad()
méthode.la source
Pourquoi ne pas utiliser un filtre habituel?
$collection->addAttributeToFilter('store_id', $store_id);
store_id est donné sous forme de colonne normale dans la table * _eav_entity , vous pouvez donc également filtrer en fonction de celle-ci. Travaillé pour moi
la source
Be my works cette solution avec core / app_emulation:
la source