2010-09-29 15 views
39

Me he quedado atrapado en esto durante las últimas horas. Lo conseguí trabajando pirateando unas pocas líneas en /lib/Varien/Data/Collection/Db.php, pero prefiero usar la solución adecuada y dejar mi núcleo intacto.Magento addFieldToFilter: Dos campos coinciden como OR, no Y

Todo lo que necesito hacer es obtener una colección y filtrarla por dos o más campos. Diga, customer_firstname y remote_ip. Aquí está mi (disfuncional y sin piratería Db.php) Código:

$collection = Mage::getModel('sales/order')->getCollection()-> 
addAttributeToSelect("*")-> 
addFieldToFilter(array(array('remote_ip', array('eq'=>'127.0.0.1')), 
array('customer_firstname', array('eq'=>'gabe'))), array('eq'=>array(1,2,3))); 

Con una acción Db.php, he intentado esto: (muestra tomada de http://magentoexpert.blogspot.com/2009/12/retrieve-products-with-specific.html)

$collection->addFieldToFilter(array(
    array('name'=>'orig_price','eq'=>'Widget A'), 
    array('name'=>'orig_price','eq'=>'Widget B'),   
)); 

Pero eso me da este error:

Warning: Illegal offset type in isset or empty in magento/lib/Varien/Data/Collection/Db.php on line 369 

Si envuelvo eso con un try/catch, se mueve a _getConditionSql() y da este error:

Warning: Invalid argument supplied for foreach() in magento/lib/Varien/Data/Collection/Db.php on line 412 

¿Alguien tiene un código funcional y operativo para hacer esto? Estoy ejecutando Magento 1.9 (Enterprise). ¡Gracias!

Respuesta

8

para filtrar por múltiples atributos usar algo como:

//for AND 
    $collection = Mage::getModel('sales/order')->getCollection() 
    ->addAttributeToSelect('*') 
    ->addFieldToFilter('my_field1', 'my_value1') 
    ->addFieldToFilter('my_field2', 'my_value2'); 

    echo $collection->getSelect()->__toString(); 

//for OR - please note 'attribute' is the key name and must remain the same, only replace //the value (my_field1, my_field2) with your attribute name 


    $collection = Mage::getModel('sales/order')->getCollection() 
     ->addAttributeToSelect('*') 
     ->addFieldToFilter(
      array(
       array('attribute'=>'my_field1','eq'=>'my_value1'), 
       array('attribute'=>'my_field2', 'eq'=>'my_value2') 
      ) 
     ); 

Para más información consultar: http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Collection_Db.html#_getConditionSql

+1

Gracias, Anda. Pero eso es para requerir ambos campos, no uno u otro. Si agrega -> getSelectSql() al final de esa consulta, le da "... WHERE (my_field1 = 'my_value1') Y (my_field2 = 'my_value2')". Es el "DONDE (myfield1 = 'myvalue1') O (myfield2 = 'myvalue2')" que estoy tratando de obtener. –

+0

He entendido mal tu publicación :); He agregado el código para O –

+3

Esto solo funciona con addAttributeToFilter en colecciones de EAV. La respuesta de Riyazkhan es la correcta. – rterrani

15

También trataron de obtener la field1 = 'a' OR field2 = 'b'

Su código no funcionó para mí .

Aquí está mi solución

$results = Mage::getModel('xyz/abc')->getCollection(); 
$results->addFieldToSelect('name'); 
$results->addFieldToSelect('keywords'); 
$results->addOrder('name','ASC'); 
$results->setPageSize(5); 

$results->getSelect()->where("keywords like '%foo%' or additional_keywords like '%bar%'"); 

$results->load(); 

echo json_encode($results->toArray()); 

Me da

SELECT name, keywords FROM abc WHERE keywords like '%foo%' OR additional_keywords like '%bar%'.

Quizás no sea el "camino del magento", pero estuve atrapado 5 horas en eso.

esperan que ayude a

+0

buen trabajo para la recogida plana. –

+0

Esta es también la mejor solución que conozco – zuzuleinen

+0

Hace algunas horas que he intentado hacer una consulta complicada para modelos de recursos personalizados. Esto es lo que finalmente funcionó. Gracias. – billmalarky

7

Gracias Anda, Su respuesta ha sido de gran ayuda !! Sin embargo, la oración OR no funcionó y obtuve un error: getCollection() "argumento no válido proporcionado para foreach".

Así que esto es lo que terminó con (nota el atributo se especifica 3 veces en lugar de 2 en este caso):

$collection->addFieldToFilter('attribute', array( 
    array('attribute'=>'my_field1','eq'=>'my_value1'),    
    array('attribute'=>'my_field2','eq'=>'my_value2'))); 

addFieldToFilter requiere en primer lugar un campo y después de condición ->link.

+0

+1 para esto. @ [La solución de Anda] (http://stackoverflow.com/questions/3826474/magento-addfieldtofilter-two-fields-match-as-or-not-and/3828722#3828722) no es correcta para una condición OR. – leek

+0

+1 para esto de hecho! Gracias. –

65

I ¡lo tengo otra forma de agregar una condición or en el campo:

->addFieldToFilter(
    array('title', 'content'), 
    array(
     array('like'=>'%$titlesearchtext%'), 
     array('like'=>'%$contentsearchtext%') 
    ) 
) 
+0

Intenté todas las respuestas y esta es la única respuesta que me ha funcionado. La respuesta de Anda para el OR estaba tratando de buscar un atributo llamado 'atributo', por lo que seguí obteniendo errores desconocidos de 'atributos' de la columna. Otras soluciones tenían los nombres de columna correctos pero no valores.Esto me dio los resultados correctos en el SQL: '... WHERE (('first_attribute' = 'algún valor') O ('second_attribute' = 'algún valor'))' – BrianVPS

+0

Probándolo de esta manera obtengo una columna no encontrada: 1054 Columna desconocida 'Array' en 'where clause'error – zuzuleinen

+1

tenga en cuenta que esta sintaxis no es correcta para addAttributeToFilter, consulte http://stackoverflow.com/a/5301457/3338098 para conocer la sintaxis – user3338098

10

Aquí está mi solución en Enterprise 1.11 (debería funcionar en C E 1.6):

$collection->addFieldToFilter('max_item_count', 
        array(
         array('gteq' => 10), 
         array('null' => true), 
        ) 
      ) 
      ->addFieldToFilter('max_item_price', 
        array(
         array('gteq' => 9.99), 
         array('null' => true), 
        ) 
      ) 
      ->addFieldToFilter('max_item_weight', 
        array(
         array('gteq' => 1.5), 
         array('null' => true), 
        ) 
      ); 

lo que resulta en este SQL:

SELECT `main_table`.* 
    FROM `shipping_method_entity` AS `main_table` 
    WHERE (((max_item_count >= 10) OR (max_item_count IS NULL))) 
     AND (((max_item_price >= 9.99) OR (max_item_price IS NULL))) 
     AND (((max_item_weight >= 1.5) OR (max_item_weight IS NULL))) 
5

Hay un poco de confusión pasando aquí, pero voy a tratar de aclarar las cosas:

Digamos que usted quería sql que parecía algo así como:

SELECT 
    `main_table`.*, 
    `main_table`.`email` AS `invitation_email`, 
    `main_table`.`group_id` AS `invitee_group_id` 
FROM 
    `enterprise_invitation` AS `main_table` 
WHERE (
    (status = 'new') 
    OR (customer_id = '1234') 
) 

Para lograr esto, su colección debe formatearse de la siguiente manera:

$collection = Mage::getModel('enterprise_invitation/invitation')->getCollection(); 

$collection->addFieldToFilter(array('status', 'customer_id'), array(
array('status','eq'=>'new'), 
array('customer_id', 'eq'=>'1234'))); 

Ahora para ver el aspecto que tiene siempre puede hacerse eco de la consulta que esto crea mediante el uso de

echo $collection->getSelect()->__toString(); 
20

O condiciones se pueden generar de esta manera:

$collection->addFieldToFilter(
    array('field_1', 'field_2', 'field_3'), // columns 
    array(// conditions 
     array(// conditions for field_1 
      array('in' => array('text_1', 'text_2', 'text_3')), 
      array('like' => '%text') 
     ), 
     array('eq' => 'exact'), // condition for field 2 
     array('in' => array('val_1', 'val_2')) // condition for field 3 
    ) 
); 

Esto generará un SQL WHERE condición algo así como:

... WHERE (
     (field_1 IN ('text_1', 'text_2', 'text_3') OR field_1 LIKE '%text') 
     OR (field_2 = 'exact') 
     OR (field_3 IN ('val_1', 'val_2')) 
    ) 

Cada matriz anidada (< condición >) genera otro conjunto de paréntesis para una condición OR.

+0

La razón por la que esto funciona es porque usa las claves en el primer param (la matriz de campos) para buscar el valor en el segundo param (la matriz de condiciones) para usar para ese campo. se me hace un poco más claro que hacer algo como: $ colección-> addFieldToFilter array (=> 'field_1' '('field_1', 'field_2'=> 'field_2'), array ( 'field_1'= > array ( array ('in' => array ('text_1', 'text_2', 'text_3'), array ('like' => '% text') ), 'field_2' => array ('eq' => 'exacto'), ) ); ' –

+0

Este filtro realmente funcionó para condiciones O. ¡Gracias! – Corgalore

+0

tenga en cuenta que esta sintaxis no es correcta para addAttributeToFilter, consulte stackoverflow.com/a/5301457/3338098 para esa sintaxis – user3338098

1

Ésta es la forma real de Magento:

$collection=Mage::getModel('sales/order') 
       ->getCollection() 
       ->addFieldToFilter(
         array(
          'customer_firstname',//attribute_1 with key 0 
          'remote_ip',//attribute_2 with key 1 
         ), 
         array(
          array('eq'=>'gabe'),//condition for attribute_1 with key 0 
          array('eq'=>'127.0.0.1'),//condition for attribute_2 
           ) 
          ) 
         ); 
2
public function testAction() 
{ 
     $filter_a = array('like'=>'a%'); 
     $filter_b = array('like'=>'b%'); 
     echo(
     (string) 
     Mage::getModel('catalog/product') 
     ->getCollection() 
     ->addFieldToFilter('sku',array($filter_a,$filter_b)) 
     ->getSelect() 
     ); 
} 

Resultado:

WHERE (((e.sku like 'a%') or (e.sku like 'b%'))) 

Fuente: http://alanstorm.com/magento_collections

2

Para crear simple o condición para la colección, utilice el formato de abajo:

$orders = Mage::getModel('sales/order')->getResourceCollection(); 
    $orders->addFieldToFilter(
     'status', 
     array(
     'processing', 
     'pending', 
    ) 
    ); 

Esto producirá SQL como esto:

WHERE (((`status` = 'processing') OR (`status` = 'pending'))) 
Cuestiones relacionadas