Filtre de collecte de produit par attribut non plane
-
16-10-2019 - |
Question
Je suis en train de faire ce qui suit:
$productCollection = Mage::getModel('catalog/product')
->getCollection();
$productCollection
->addAttributeToFilter('my_attribute', 1);
my_attribute
est pas dans les tables à plat, mais les tables plates sont activées.
Je continue à obtenir la collection complète.
La raison semble être \Mage_Catalog_Model_Resource_Product_Collection::addAttributeToSelect
:
$columns = $this->getEntity()->getAttributeForSelect($attributeCode);
Non $this->getEntity()
est une instance de Mage_Catalog_Model_Resource_Product_Flat
qui va chercher les champs plats -. Et si aucun se trouve, juste retourne null
Quelle est une manière propre d'ajouter un attribut non-plat au filtre de collection?
Dans mon cas, il n'a pas de sens, d'ajouter l'attribut à la table plate.
La solution
Vous pourriez joindre à la table nécessaire vous.
$productCollection = Mage::getModel('catalog/product')
->getCollection();
$table = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getBackend()->getTable();
$attributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getAttributeId();
$productCollection->getSelect()->join(array('attributeTable' => $table), 'e.entity_id = attributeTable.entity_id', array('my_attribute' => 'attributeTable.value'))
->where("attributeTable.attribute_id = ?", $attributeId)
->where("attributeTable.value = ?", 1);
Vous pouvez joindre par store_id aussi.
Autres conseils
Un hack (CE 1.6.2.0+) est de passer la condition comme un tableau et croyez-le ou non cela fonctionne comme prévu:
$collection->addFieldToFilter(array(array('attribute' => 'my_attribute', 'eq' => 1)));
La raison fonctionne la réponse de ColinM est due au code dans la méthode de app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php
de addAttributeToFilter
. Si vous utilisez ce format de tableau, il ne remet pas addAttributeToSelect
. En mode plat, addAttributeToSelect
échoue silencieusement si l'attribut est pas dans la table plate.
(ci-dessous est une re-hachage de ma réponse sur https://stackoverflow.com/questions/6271284/can-i-add-other-attributes-to-magentos-flat-product-catalog-table/17021620 - Je ne suis pas sûr de ce que l'étiquette est pour cela, mais sais que je l'aurais trouvé utile)
I cherché une solution « propre » pour la collecte du mode de sélection et de filtrage plat sur les attributs non planes, qui:
- ne nécessite pas l'attribut d'avoir des paramètres spécifiques dans l'admin (il peut être ajouté par un utilisateur, ou caché à l'extrémité avant)
- fonctionne à la fois plat et mode non-plat
J'utilisé la collection de produits associés, mais cela s'applique à toute collection de EAV.
Code défaut:
$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
->addAttributeToSelect( 'my_custom_attribute' )
->addAttributeToFilter( 'my_custom_attribute', 3 )
;
En mode plat, le code ci-dessus échoue en silence pour sélectionner ou filtre sur l'attribut si elle se produit pas être dans la table plate.
Ajout à la sélection:
$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
->joinAttribute( 'my_custom_attribute', 'catalog_product/my_custom_attribute', 'entity_id', null, 'left' )
->addAttributeToSelect( 'my_custom_attribute' )
;
La méthode joinAttribute
ajoute une jointure à la requête pour l'attribut spécifique demandé. Il fonctionne toujours lorsque l'attribut est déjà dans la table à plat, mais sera un peu moins efficace que purement en utilisant la table plate.
Je l'ai utilisé un left
rejoindrai, pour vous assurer qu'il va chercher des produits si my_custom_attribute
n'est pas défini sur ces produits. Un changement qui pour inner
si vous n'êtes intéressé que par les lignes où my_custom_attribute
est réglé.
Ajout dans le filtre (comme par ColinM ci-dessus):
$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
->addAttributeToFilter( array( array( 'attribute' => 'my_custom_attribute', 'eq' => 3 ) ) )
;
Le code ci-dessus ajouter à la sélectionner, ainsi que d'obéir votre filtre.
(testé dans CE 1.6.2.0)
Dans le module Mage_Rss
ils ont utilisé la méthode a-hacky pour désactiver les tables plates. Ils utilisent le fait, que les tables plats sont toujours hors dans le magasin d'administration et ainsi émulent juste le magasin d'administration.
class Mage_Rss_Helper_Data {
[...]
/**
* Disable using of flat catalog and/or product model to prevent limiting results to single store. Probably won't
* work inside a controller.
*
* @return null
*/
public function disableFlat()
{
/* @var $flatHelper Mage_Catalog_Helper_Product_Flat */
$flatHelper = Mage::helper('catalog/product_flat');
if ($flatHelper->isEnabled()) {
/* @var $emulationModel Mage_Core_Model_App_Emulation */
$emulationModel = Mage::getModel('core/app_emulation');
// Emulate admin environment to disable using flat model - otherwise we won't get global stats
// for all stores
$emulationModel->startEnvironmentEmulation(0, Mage_Core_Model_App_Area::AREA_ADMINHTML);
}
}
Après avoir démarré l'émulation vous devez réinitialiser avec emulationModel->stopEnvironmentEmulation()
lorsque vous créez l'attribut, il devrait être au niveau mondial et filtrables. De cette façon, il sera utilisable dans la navigation layared. il faudra également l'attribut à un menu déroulant ou multiselect. Personnellement, je déconseillant la modification des fichiers de base pour répondre à vos besoins dans ce cas