Magento addFieldToFilter:两个字段,匹配为 OR,而不是 AND
Posted
技术标签:
【中文标题】Magento addFieldToFilter:两个字段,匹配为 OR,而不是 AND【英文标题】:Magento addFieldToFilter: Two fields, match as OR, not AND 【发布时间】:2010-09-29 22:53:31 【问题描述】:在过去的几个小时里,我一直被困在这个问题上。我通过修改/lib/Varien/Data/Collection/Db.php
中的几行代码来实现它,但我宁愿使用正确的解决方案,并且不影响我的核心。
我需要做的就是获取一个集合并按两个或多个字段对其进行过滤。比如customer_firstname
和remote_ip
。这是我的(没有破解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)));
用股票Db.php
,我试过这个:(样本取自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'),
));
但这给了我这个错误:
Warning: Illegal offset type in isset or empty in magento/lib/Varien/Data/Collection/Db.php on line 369
如果我用 try/catch 包装它,那么它会移动到 _getConditionSql() 并给出这个错误:
Warning: Invalid argument supplied for foreach() in magento/lib/Varien/Data/Collection/Db.php on line 412
有没有人有任何工作的、功能性的代码来做这件事?我正在运行 Magento 1.9(企业版)。谢谢!
【问题讨论】:
【参考方案1】:我还有另一种方法可以在字段中添加or
条件:
->addFieldToFilter(
array('title', 'content'),
array(
array('like'=>'%$titlesearchtext%'),
array('like'=>'%$contentsearchtext%')
)
)
【讨论】:
我尝试了所有答案,这是唯一对我有用的答案。 Anda 对 OR 的回答是试图搜索一个名为“attribute”的属性,所以我不断收到未知列的“attribute”错误。其他解决方案具有正确的列名但没有值。这在 SQL 中给了我正确的结果:... WHERE (('first_attribute' = 'some value') OR ('second_attribute' = 'some value'))
尝试这种方式我得到一个未找到的列:1054 Unknown column 'Array' in 'where Clause'错误
请注意,此语法不适用于 addAttributeToFilter,请参阅 ***.com/a/5301457/3338098 了解该语法【参考方案2】:
OR 条件可以这样生成:
$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
)
);
这将生成一个 SQL WHERE 条件,例如:
... 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'))
)
每个嵌套数组(
【讨论】:
这个工作的原因是它使用第一个参数(字段数组)中的键来查找第二个参数(条件数组)中用于该字段的值。我发现这样做更清楚:$collection->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' => 'exact'), ) );
这个过滤器实际上适用于 OR 条件。谢谢!
请注意,此语法不适用于 addAttributeToFilter,请参阅 ***.com/a/5301457/3338098 了解该语法【参考方案3】:
我也尝试获取field1 = 'a' OR field2 = 'b'
你的代码对我不起作用。
这是我的解决方案
$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());
它给了我
SELECT name, keywords FROM abc WHERE keywords like '%foo%' OR additional_keywords like '%bar%'
.
这可能不是“magento 的方式”,但我被困了 5 个小时。
希望对你有帮助
【讨论】:
这也是我所知道的最好的解决方案 我已经尝试让一个复杂的查询为自定义资源模型工作了几个小时。这就是最终奏效的方法。谢谢。【参考方案4】:这是我在 Enterprise 1.11 中的解决方案(应该在 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),
)
);
这会导致这个 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】:要按多个属性进行过滤,请使用以下内容:
//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')
)
);
更多信息请查看: http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Collection_Db.html#_getConditionSql
【讨论】:
谢谢,安达。但这是因为需要两个字段,而不是其中一个。如果您将 ->getSelectSql() 添加到该查询的末尾,它会为您提供“...WHERE (my_field1 = 'my_value1') AND (my_field2 = 'my_value2')”。这是我想要得到的“WHERE (myfield1 = 'myvalue1') OR (myfield2 = 'myvalue2')”。 这仅适用于 EAV 集合中的 addAttributeToFilter。 Riyazkhan 的答案是正确的。【参考方案6】:谢谢安达,你的帖子帮了大忙!! 然而,OR 语句对我来说不太有效,我得到了一个错误: getCollection() "为 foreach 提供的参数无效".
所以这就是我的结尾(注意在这种情况下属性被指定了 3 次而不是 2 次):
$collection->addFieldToFilter('attribute', array(
array('attribute'=>'my_field1','eq'=>'my_value1'),
array('attribute'=>'my_field2','eq'=>'my_value2') ));
addFieldToFilter 首先需要一个字段,然后是条件 -> link.
【讨论】:
为此 +1。 @Anda's solution 不适合 OR 条件。【参考方案7】:这里有点混乱,但让我试着澄清一下:
假设你想要看起来像这样的 sql:
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')
)
为了实现这一点,您的收藏需要像这样格式化:
$collection = Mage::getModel('enterprise_invitation/invitation')->getCollection();
$collection->addFieldToFilter(array('status', 'customer_id'), array(
array('status','eq'=>'new'),
array('customer_id', 'eq'=>'1234') ));
现在看看它是什么样子的,你总是可以使用
回显它创建的查询echo $collection->getSelect()->__toString();
【讨论】:
【参考方案8】:这是真正的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
)
)
);
【讨论】:
【参考方案9】: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()
);
结果:
WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
来源:http://alanstorm.com/magento_collections
【讨论】:
【参考方案10】:要为收集创建简单的 OR 条件,请使用以下格式:
$orders = Mage::getModel('sales/order')->getResourceCollection();
$orders->addFieldToFilter(
'status',
array(
'processing',
'pending',
)
);
这将产生如下 SQL:
WHERE (((`status` = 'processing') OR (`status` = 'pending')))
【讨论】:
以上是关于Magento addFieldToFilter:两个字段,匹配为 OR,而不是 AND的主要内容,如果未能解决你的问题,请参考以下文章
过滤 Magento 集合而不是产品,使用 distinct
Magento 2中文手册教程 - 如何获得 Magento 2
安装完magento后,其他电脑无法访问magento,URL自动跳转到http://localhost/magento