Magento: recupere productos con un valor de atributo específico

78

En mi código de bloque, estoy tratando de recuperar mediante programación una lista de productos que tienen un atributo con un valor específico.

Alternativamente, si eso no es posible, ¿cómo se pueden recuperar todos los productos y luego filtrarlos para enumerar los productos con un atributo específico?

¿Cómo realizaría una búsqueda utilizando filtros booleanos estándar ANDo ORpara hacer coincidir un subconjunto de mis productos?

cristiano
fuente

Respuestas:

160

Casi todos los modelos de Magento tienen un objeto de colección correspondiente que se puede usar para buscar múltiples instancias de un modelo.

Para crear una instancia de una colección de productos, haga lo siguiente

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

Los productos son un modelo de estilo EAV de Magento, por lo que deberá agregar cualquier atributo adicional que desee devolver.

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

//fetch name and orig_price into data
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

Hay varias sintaxis para configurar filtros en colecciones. Siempre uso el detallado a continuación, pero es posible que desee inspeccionar la fuente de Magento para ver formas adicionales de utilizar los métodos de filtrado.

A continuación se muestra cómo filtrar por un rango de valores (mayor que Y menor que)

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

//filter for products whose orig_price is greater than (gt) 100
$collection->addFieldToFilter(array(
    array('attribute'=>'orig_price','gt'=>'100'),
)); 

//AND filter for products whose orig_price is less than (lt) 130
$collection->addFieldToFilter(array(
    array('attribute'=>'orig_price','lt'=>'130'),
));

Mientras que esto filtrará por un nombre que sea igual a una cosa U otra.

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

//filter for products who name is equal (eq) to Widget A, or equal (eq) to Widget B
$collection->addFieldToFilter(array(
    array('attribute'=>'name','eq'=>'Widget A'),
    array('attribute'=>'name','eq'=>'Widget B'),        
));

Se puede encontrar una lista completa de los condicionales breves admitidos (eq, lt, etc.) en el _getConditionSqlmétodo delib/Varien/Data/Collection/Db.php

Finalmente, todas las colecciones de Magento se pueden iterar (la clase de colección base implementa una de las interfaces del iterador). Así es como tomará sus productos una vez que se establezcan los filtros.

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name');  
$collection->addAttributeToSelect('orig_price');    

//filter for products who name is equal (eq) to Widget A, or equal (eq) to Widget B
$collection->addFieldToFilter(array(
    array('attribute'=>'name','eq'=>'Widget A'),
    array('attribute'=>'name','eq'=>'Widget B'),        
));

foreach ($collection as $product) {
    //var_dump($product);
    var_dump($product->getData());
}
Alan Storm
fuente
Muchas gracias por la respuesta detallada. Me has puesto en el camino correcto. Hice un var_dump de los resultados de su código de ejemplo. Debido a que el atributo con el que estoy trabajando es un elemento de selección múltiple, obtengo una identificación numérica en los resultados, por lo que la comparación de texto no funciona. EG $ this-> colección-> addFieldToFilter (array (array ('atributo' => 'cw_category', 'eq' => 'Aero'), array ('atributo' => 'cw_category', 'eq' => ' Track '), array (' atributo '=>' cw_category ',' eq '=>' Touring '))); Está devolviendo 'cw_category' => string ', 536,535,534' (longitud = 12)
Christian
No puedo ayudarlo específicamente sin investigar mucho (el representante de StackOverflow es bueno, pero no paga las facturas). Dos caminos para que usted siga. Primero, como se mencionó, consulte _getConditionSql para obtener una lista de todos los posibles operadores de comparación. Es posible que pueda arreglárselas con una cláusula similar o tal vez una entrada. En segundo lugar, si comprueba PHPDoc para el método addAttributeToFilter en Mage_Eav_Model_Entity_Collection_Abstract, verá que uno de los valores esperados del primer parámetro es un Mage_Eav_Model_Entity_Attribute. Eso podría llevarlo por el camino correcto.
Alan Storm
1
En la muestra de código final, sus matrices comienzan con 'name' => 'orig_price': ¿es correcto? ¿No debería ser así 'attribute' => 'name'?
Andy
1
@johnsnails eso es muy posible, esta publicación en 9 años. Es posible que mi respuesta haya incluido información inexacta, o que la API haya cambiado. No hago suficiente trabajo con Magento en estos días para estar seguro.
Alan Storm
1
@AlanStorm Parece que fue solo un error de copiar / pegar de otra muestra de código en su respuesta. Voy a editar la respuesta y rectificarla.
Andy
7

Esta es una continuación de mi pregunta original para ayudar a otros con el mismo problema. Si necesita filtrar por un atributo, en lugar de buscar manualmente la identificación, puede usar el siguiente código para recuperar todos los pares de identificación y valor para un atributo. Los datos se devuelven como una matriz con el nombre del atributo como clave.

function getAttributeOptions($attributeName) {
    $product = Mage::getModel('catalog/product');
    $collection = Mage::getResourceModel('eav/entity_attribute_collection')
              ->setEntityTypeFilter($product->getResource()->getTypeId())
              ->addFieldToFilter('attribute_code', $attributeName);

    $_attribute = $collection->getFirstItem()->setEntity($product->getResource());
    $attribute_options  = $_attribute->getSource()->getAllOptions(false);
    foreach($attribute_options as $val) {
        $attrList[$val['label']] = $val['value'];
    }   

    return $attrList;
}

Aquí hay una función que puede usar para obtener productos por su ID de conjunto de atributos. Recuperado usando la función anterior.

function getProductsByAttributeSetId($attributeSetId) {
   $products = Mage::getModel('catalog/product')->getCollection();
   $products->addAttributeToFilter('attribute_set_id',$attributeSetId);

   $products->addAttributeToSelect('*');

   $products->load();
   foreach($products as $val) {
     $productsArray[] = $val->getData();
  }

  return $productsArray;
}
cristiano
fuente
5
$attribute = Mage::getModel('eav/entity_attribute')
                ->loadByCode('catalog_product', 'manufacturer');

$valuesCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
            ->setAttributeFilter($attribute->getData('attribute_id'))
            ->setStoreFilter(0, false);

$preparedManufacturers = array();            
foreach($valuesCollection as $value) {
    $preparedManufacturers[$value->getOptionId()] = $value->getValue();
}   


if (count($preparedManufacturers)) {
    echo "<h2>Manufacturers</h2><ul>";
    foreach($preparedManufacturers as $optionId => $value) {
        $products = Mage::getModel('catalog/product')->getCollection();
        $products->addAttributeToSelect('manufacturer');
        $products->addFieldToFilter(array(
            array('attribute'=>'manufacturer', 'eq'=> $optionId,          
        ));

        echo "<li>" . $value . " - (" . $optionId . ") - (Products: ".count($products).")</li>";
    }
    echo "</ul>";
}
verheesj
fuente
3

Para obtener TEXTatributos agregados desde el administrador al front-end en la página de listado de productos.

Gracias Anita Mourya

He descubierto que hay dos métodos. Digamos que el atributo de producto llamado "na_author" se agrega desde el backend como campo de texto.

MÉTODO 1

en list.phtml

<?php $i=0; foreach ($_productCollection as $_product): ?>

PARA CADA PRODUCTO CARGUE POR SKU Y OBTENGA ATRIBUTOS DENTRO PARA CADA

<?php
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$_product->getSku());
$author = $product['na_author'];
?>

<?php
if($author!=""){echo "<br /><span class='home_book_author'>By ".$author ."</span>";} else{echo "";}
?>

MÉTODO 2

Mage/Catalog/Block/Product/List.phtml OVER RIDE y establecer en 'carpeta local'

es decir, copiar desde

Mage/Catalog/Block/Product/List.phtml

y PEGAR A

app/code/local/Mage/Catalog/Block/Product/List.phtml

cambie la función agregando 2 líneas que se muestran en negrita a continuación.

protected function _getProductCollection()
{
       if (is_null($this->_productCollection)) {
           $layer = Mage::getSingleton('catalog/layer');
           /* @var $layer Mage_Catalog_Model_Layer */
           if ($this->getShowRootCategory()) {
               $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
           }

           // if this is a product view page
           if (Mage::registry('product')) {
               // get collection of categories this product is associated with
               $categories = Mage::registry('product')->getCategoryCollection()
                   ->setPage(1, 1)
                   ->load();
               // if the product is associated with any category
               if ($categories->count()) {
                   // show products from this category
                   $this->setCategoryId(current($categories->getIterator()));
               }
           }

           $origCategory = null;
           if ($this->getCategoryId()) {
               $category = Mage::getModel('catalog/category')->load($this->getCategoryId());

               if ($category->getId()) {
                   $origCategory = $layer->getCurrentCategory();
                   $layer->setCurrentCategory($category);
               }
           }
           $this->_productCollection = $layer->getProductCollection();

           $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

           if ($origCategory) {
               $layer->setCurrentCategory($origCategory);
           }
       }
       **//CMI-PK added na_author to filter on product listing page//
       $this->_productCollection->addAttributeToSelect('na_author');**
       return $this->_productCollection;

}

y te alegrarás de verlo .... !!

Pragnesh Karia
fuente
2

crear nombre de atributo es " price_screen_tab_name". y acceda utilizando esta sencilla fórmula.

<?php $_product = $this->getProduct(); ?>
<?php echo $_product->getData('price_screen_tab_name');?>
Pratik Kamani
fuente
0

He añadido línea

$this->_productCollection->addAttributeToSelect('releasedate');

en

app / code / core / Mage / Catalog / Block / Product / List.php en la línea 95

en función _getProductCollection()

y luego llamarlo

app / design / frontend / default / hellopress / template / catalog / product / list.phtml

Escribiendo código

<div><?php echo $this->__('Release Date: %s', $this->dateFormat($_product->getReleasedate())) ?>
</div>

Ahora está funcionando en Magento 1.4.x

Anita Mourya
fuente