addAttributeToSelect ne fonctionne pas avec core / resource_iterator?

8
public function run()
{
    $products = Mage::getModel('catalog/product')
            ->getCollection()
            ->addFinalPrice()
            ->addAttributeToSelect('name')

    Mage::getSingleton('core/resource_iterator')
            ->walk($products->getSelect()->limit(10), array(array($this, 'getLine')));

}

public function getLine($args)
{
    var_dump($args['row']);
}

Dans ma getLine()méthode, je reçois non, namemais addFinalPrice()fonctionne:

array(16) {
  ["entity_id"]=>
  string(2) "61"
  ["entity_type_id"]=>
  string(1) "4"
  ["attribute_set_id"]=>
  string(2) "10"
  ["type_id"]=>
  string(6) "simple"
  ["sku"]=>
  string(15) "50-F01010001-03"
  ["has_options"]=>
  string(1) "0"
  ["required_options"]=>
  string(1) "0"
  ["created_at"]=>
  string(19) "2011-07-05 18:30:48"
  ["updated_at"]=>
  string(19) "2014-09-04 07:34:21"
  ["indexed_price"]=>
  string(7) "14.5000"
  ["price"]=>
  string(7) "14.5000"
  ["final_price"]=>
  string(7) "14.5000"
  ["minimal_price"]=>
  string(7) "14.5000"
  ["min_price"]=>
  string(7) "14.5000"
  ["max_price"]=>
  string(7) "14.5000"
  ["tier_price"]=>
  NULL
}

Même problème avec image, priceet tous les autres attributs.

PiTheNumber
la source

Réponses:

7

Malheureusement, le core/iteratormodèle de ressource ne fonctionne pas bien avec les modèles EAV, car il fonctionne directement avec la requête et n'utilise aucune des fonctionnalités spécifiques à la collection.

C'est ce qui se produit généralement lors du chargement d'une collection EAV (je vais simplifier un peu):

  • sélectionner les données de base dans la table d'entités (c'est ce $collection->getSelect()que
  • charger les attributs des tables de valeurs avec une requête supplémentaire et ajouter ces données à chaque modèle chargé

Tout cela se passe dans la load()méthode (voyez Mage_Eav_Model_Entity_Collection_Abstract::_loadAttributes()si vous voulez voir les détails de l'implémentation)

Étant donné que la raison d'utiliser l'itérateur de ressources est généralement que vous ne voulez pas charger toutes les données en même temps, vous ne pouvez pas utiliser cette fonctionnalité de manière raisonnable.

J'ai essayé de créer une seule requête avec des jointures à la place, mais j'ai vite rencontré le problème que MySQL n'autorise "que" 63 jointures à la fois. Si vous n'avez besoin que de quelques attributs, cela pourrait vous convenir.

Sinon, votre meilleur pari est de charger et de traiter la collection en morceaux comme ceci:

$ids = Mage::getModel('catalog/product')
    ->getCollection()
    ->getAllIds();

$page = 1;
do {
    $collection = Mage::getModel('catalog/product')
        ->getCollection()
        ->addIdFilter($ids)
        ->setPageSize(100)
        ->setPage($page);
    $results = $collection->load();
    // do stuff ...
    $page++;
} while ($results->count());
Fabian Schmengler
la source
J'ai utilisé l'itérateur en raison d'un problème de limite de mémoire, mais il s'est avéré que l'utilisation de l'itérateur utilise encore plus de mémoire. J'ai corrigé qu'il revienne à la collection normale et ini_set('memory_limit','512M');.
PiTheNumber
7

Vous devez utiliser le deuxième paramètre 'inner'comme ceci:

$products = Mage::getModel('catalog/product')
     ->getCollection()
     ->addAttributeToSelect(array('name', 'image'), 'inner');

Voir: /programming/24614533/magento-collection-iterator-cannot-get-additional-attribute

PiTheNumber
la source
Il s'agit de la solution JOIN à laquelle je faisais référence. Bien si vous n'avez besoin que de quelques attributs, mais ne l'essayez pas avecaddAttributeToSelect('*')
Fabian Schmengler
Utilisez 'left' si vous souhaitez inclure des entités où l'attribut eav n'est pas défini du tout.
siliconrockstar