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.

Était-ce utile?

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top