Magento addFieldToFilter: deux champs, match as OR, not et

je suis coincé sur cette depuis quelques heures. J'ai eu de travail par le piratage de quelques lignes dans /lib/Varien/Data/Collection/Db.php, mais je préfère utiliser la bonne solution et laisser mon cœur intact.

Tout ce que je dois faire est d'obtenir une collection et filtrer par deux ou plusieurs champs. Dire, customer_firstname et remote_ip. Voici mon (dysfonctionnel sans hacking Db.php) code:

$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)));

avec un stock Db.php, j'ai essayé ceci: (échantillon prélevé à partir 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'),           
));

Mais ça me donne cette erreur:

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

si je l'emballe avec un try / catch, alors il se déplace dans _getConditionSql () et donne cette erreur:

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

est-ce que quelqu'un a un code fonctionnel pour faire ça? Je dirige Magento 1.9 (Enterprise). Merci!

42
demandé sur dayuloli 2010-09-30 02:53:31

10 réponses

j'en ai une autre façon d'ajouter un or condition dans le champ:

->addFieldToFilter(
    array('title', 'content'),
    array(
        array('like'=>'%$titlesearchtext%'), 
        array('like'=>'%$contentsearchtext%')
    )
)
69
répondu Riyazkhan 2013-09-02 23:29:32

OU conditions peuvent être générés comme ceci:

$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
    )
);

cela générera un SQL où la condition quelque chose comme:

... 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'))
    )

chaque tableau imbriqué () génère un autre ensemble de parenthèses pour une condition ou.

22
répondu CJ Dennis 2016-01-19 18:18:53

j'ai aussi essayé de mettre les field1 = 'a' OR field2 = 'b'

votre code n'a pas fonctionné pour moi.

Voici ma solution

$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());

Il me donne

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

ce n'est peut-être pas la "voie de magento" mais j'étais coincé 5 heures là-dessus.

j'Espère que ça aidera

15
répondu user654539 2015-07-13 09:41:37

voici ma solution dans L'entreprise 1.11 (devrait fonctionner dans 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),
                    )
            );

ce qui donne ce 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)))
10
répondu Michael Payne 2012-07-20 13:32:39

filtrer par plusieurs attributs d'utiliser quelque chose comme:

//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')
            )
        );

Pour plus d'informations, consultez: http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Collection_Db.html#_getConditionSql

9
répondu Anda B 2012-04-03 17:13:48

Merci Anda, votre post a été d'une grande aide!! Cependant la phrase ou n'a pas tout à fait fonctionné pour moi et je recevais une erreur: getCollection ()"argument invalide fourni pour foreach".

donc c'est ce que j'ai terminé avec (notez que l'attribut est spécifié 3 fois au lieu de 2 dans ce cas):

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

addFieldToFilter exige tout d'abord un champ et condition -> lien.

7
répondu jazkat 2011-05-13 07:06:17

il y a un peu de confusion ici, mais laissez-moi essayer de clarifier les choses:

disons que vous vouliez sql qui ressemblait à quelque chose comme:

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')
)

pour ce faire, votre collection doit être formatée comme ceci:

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

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

maintenant pour voir à quoi cela ressemble vous pouvez toujours faire écho à la requête que cela crée en utilisant

echo $collection->getSelect()->__toString();
5
répondu phpCodeNinja 2012-12-19 20:30:16
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()
        );
}

Résultat:

WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
http://alanstorm.com/magento_collections

2
répondu De Nguyen 2015-07-10 06:37:03

pour créer simple ou condition pour la collecte, utilisez le format ci-dessous:

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

Ceci va produire SQL comme ceci:

WHERE (((`status` = 'processing') OR (`status` = 'pending')))
2
répondu XPS 2016-09-06 05:39:33

C'est le réel magento façon:

    $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
                                )
                            )
                        );
1
répondu Gabriel 2013-06-03 15:59:20