php - Magento addFieldToFilter: dos campos, coinciden como OR, no como Y
magento-1.9 (10)
Estuve atascado en esto durante las últimas horas. Lo conseguí trabajando hackeando unas pocas líneas en /lib/Varien/Data/Collection/Db.php
, pero prefiero usar la solución adecuada y dejar mi núcleo intacto.
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 código (disfuncional sin hackear Db.php
):
$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 un stock Db.php
, probé 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 algún código operativo y funcional para hacer esto? Estoy ejecutando Magento 1.9 (Enterprise). ¡Gracias!
¡Gracias Anda, tu publicación ha sido de gran ayuda! Sin embargo, la oración OR no funcionó para mí y recibí un error: getCollection () "argumento inválido suministrado para foreach" .
Así que esto es lo que terminé con (observe el atributo que 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 primero requiere un campo y luego condición -> link.
Aquí está mi solución en Enterprise 1.11 (debería funcionar en CE 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)))
Esta es la verdadera manera 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
)
)
);
Hay un poco de confusión pasando aquí, pero déjame intentar aclarar cosas:
Digamos que querías SQL que se pareciera a algo así:
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 así:
$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 cómo se ve, siempre puede hacerse eco de la consulta que esto crea al usar
echo $collection->getSelect()->__toString();
O las condiciones se pueden generar así:
$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á una condición SQL DONDE 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.
Para crear una condición OR sencilla para la recopilación, use el siguiente formato:
$orders = Mage::getModel(''sales/order'')->getResourceCollection();
$orders->addFieldToFilter(
''status'',
array(
''processing'',
''pending'',
)
);
Esto producirá SQL así:
WHERE (((`status` = ''processing'') OR (`status` = ''pending'')))
Para filtrar por atributos múltiples, use 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 obtener más información, consulte: http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Collection_Db.html#_getConditionSql
También traté de obtener el field1 = ''a'' OR field2 = ''b''
Tu 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%''
.
Tal vez no sea el "camino del magento", pero estuve atrapado 5 horas en eso.
Espero que ayude
Tengo otra forma de agregar una or
una condición en el campo:
->addFieldToFilter(
array(''title'', ''content''),
array(
array(''like''=>''%$titlesearchtext%''),
array(''like''=>''%$contentsearchtext%'')
)
)
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%'')))