如何按属性 1 = 值 1 和(属性 2 = 值 2 或属性 3 = 值 2)过滤 Magento 销售订单集合?我可以写 WHERE {COND1} 和 {COND2} 或 {COND3},但我不能对 AND ({COND2} 或 {COND3}) 进行分组
首先,这不是重复的 AFAIK,我已经看到了这一点,它在 1.3.2 版中效果很好,但在企业版 1.11.1 中效果不佳。这是我正在尝试做的...获取在定义的日期范围内创建或更新的Magento订单,这些订单的状态为"正在处理"。以下是在以前版本中有效的代码,但在我版本中不起作用:
$orderIds = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('status', 'processing')
->addFieldToFilter(array(
array(
'attribute' => 'created_at',
'from' => $fromDate->toString('yyyy-MM-dd HH:mm:ss'),
'to' => $toDate->toString('yyyy-MM-dd HH:mm:ss'),
),
array(
'attribute' => 'updated_at',
'from' => $fromDate->toString('yyyy-MM-dd HH:mm:ss'),
'to' => $toDate->toString('yyyy-MM-dd HH:mm:ss'),
),
));
这是它生成的 SQL,以及由此产生的错误:
SELECT `main_table`.* FROM `sales_flat_order` AS `main_table`
WHERE (status = 'processing') AND (Array = '')
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Array' in 'where clause'
在挖掘代码时,我在lib/Varien/Data/Collection/Db中找到了addFieldToFilter
函数.php
/**
* Add field filter to collection
*
* @see self::_getConditionSql for $condition
* @param string $field
* @param null|string|array $condition
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
public function addFieldToFilter($field, $condition=null)
{
$field = $this->_getMappedField($field);
$this->_select->where($this->_getConditionSql($field, $condition),
null, Varien_Db_Select::TYPE_CONDITION);
return $this;
}
// **********************************************
// ** Different from addFieldToFilter in 1.3.2 **
// **********************************************
/**
* Add field filter to collection
*
* If $attribute is an array will add OR condition with following format:
* array(
* array('attribute'=>'firstname', 'like'=>'test%'),
* array('attribute'=>'lastname', 'like'=>'test%'),
* )
*
* @see self::_getConditionSql for $condition
* @param string|array $attribute
* @param null|string|array $condition
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
public function addFieldToFilter($field, $condition=null)
{
$field = $this->_getMappedField($field);
$this->_select->where($this->_getConditionSql($field, $condition));
return $this;
}
看起来addFieldToFilter
曾经接受第一个参数作为数组,但现在它必须是一个字符串......有趣,所以我尝试了以下内容,但运气为零......
$orderIds = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('status', 'processing')
->addFieldToFilter('attribute', array(
array(
'attribute' => 'created_at',
'from' => $fromDate->toString('yyyy-MM-dd HH:mm:ss'),
'to' => $toDate->toString('yyyy-MM-dd HH:mm:ss'),
),
array(
'attribute' => 'updated_at',
'from' => $fromDate->toString('yyyy-MM-dd HH:mm:ss'),
'to' => $toDate->toString('yyyy-MM-dd HH:mm:ss'),
),
));
SELECT `main_table`.* FROM `sales_flat_order` AS `main_table`
WHERE (status = 'processing')
AND ((
(attribute >= '2012-06-13 17:52:01' AND attribute <= '2012-06-15 17:52:01')
OR (attribute >= '2012-06-13 17:52:01' AND attribute <= '2012-06-15 17:52:01')
))
我知道我可以通过操作 SQL 来做到这一点,但我真的很想知道如何"Magento 方式"做到这一点,如果有的话......
顺便说一句,我也尝试使用addAttributeToFilter
,错误消息是"无法确定字段名称"。
更新
我在Mage_Sales_Model_Resource_Order_Collection
中发现了两个看起来半有前途的功能,但它们仍然不是我想要的。
/**
* Add field search filter to collection as OR condition
*
* @see self::_getConditionSql for $condition
*
* @param string $field
* @param null|string|array $condition
* @return Mage_Sales_Model_Resource_Order_Collection
*/
public function addFieldToSearchFilter($field, $condition = null)
{
$field = $this->_getMappedField($field);
$this->_select->orWhere($this->_getConditionSql($field, $condition));
return $this;
}
/**
* Specify collection select filter by attribute value
*
* @param array $attributes
* @param array|integer|string|null $condition
* @return Mage_Sales_Model_Resource_Order_Collection
*/
public function addAttributeToSearchFilter($attributes, $condition = null)
{
if (is_array($attributes) && !empty($attributes)) {
$this->_addAddressFields();
$toFilterData = array();
foreach ($attributes as $attribute) {
$this->addFieldToSearchFilter($this->_attributeToField($attribute['attribute']), $attribute);
}
} else {
$this->addAttributeToFilter($attributes, $condition);
}
return $this;
}
当我更新我的代码时,我非常接近我想要的结果,但是我真正想要的是拥有CONDITION1和(CONDITION2或CONDITION3)
$orderIds = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('status', 'processing')
->addAttributeToSearchFilter(array(
array(
'attribute' => 'created_at',
'from' => $fromDate->toString('yyyy-MM-dd HH:mm:ss'),
'to' => $toDate->toString('yyyy-MM-dd HH:mm:ss'),
),
array(
'attribute' => 'updated_at',
'from' => $fromDate->toString('yyyy-MM-dd HH:mm:ss'),
'to' => $toDate->toString('yyyy-MM-dd HH:mm:ss'),
),
));
SELECT `main_table`.*,
`billing_o_a`.`firstname`,
`billing_o_a`.`lastname`,
`billing_o_a`.`telephone`,
`billing_o_a`.`postcode`,
`shipping_o_a`.`firstname`,
`shipping_o_a`.`lastname`,
`shipping_o_a`.`telephone`,
`shipping_o_a`.`postcode`
FROM `sales_flat_order` AS `main_table`
LEFT JOIN `sales_flat_order_address` AS `billing_o_a`
ON (main_table.entity_id = billing_o_a.parent_id AND billing_o_a.address_type = 'billing')
LEFT JOIN `sales_flat_order_address` AS `shipping_o_a`
ON (main_table.entity_id = shipping_o_a.parent_id AND shipping_o_a.address_type = 'shipping')
WHERE (status = 'processing')
OR (created_at >= '2012-06-16 16:43:38' AND created_at <= '2012-06-18 16:43:38')
OR (updated_at >= '2012-06-16 16:43:38' AND updated_at <= '2012-06-18 16:43:38')
请注意,FLAT TABLE 和 EAV 集合使用不同的语法!
向 EAV 集合添加 OR 条件
请注意,为同一属性指定 OR 条件时,语法与要使用两个不同属性时不同。
使用 $collection->load(true)
进行测试并将指定的过滤器视为 SQL(我发现这样更容易理解)。
对于 EAV 集合,请使用 addAttributeToFilter()
或 addFieldToFilter()
,但第一个集合可以采用可选的第三个$joinType
参数。
如何在 EAV 集合上为 ONE 属性添加 OR 筛选器:属性代码是第一个参数,条件是第二个参数。
例如:$col->addFieldToFilter('name', array(array('like' => 'M%'), array('like' => '%O'))); // (get items whose name starts with M OR ends with O)
如何在EAV集合上为不同的属性添加OR过滤器:只传递一个参数,一个带有属性的条件数组。
向平面表集合添加 OR 条件
在平面表集合上指定具有单个属性的 OR 筛选器与在 EAV 集合上指定相同。
例如:$col->addFieldToFilter('name', array(array('like' => 'M%'), array('like' => '%O'))); // get items whose name start with M OR end with O
要在OR条件中连接多个属性,语法与EAV集合不同(注意:这在Magento 1.6中已损坏)
例如:$col->addFieldToFilter(array('weight', 'name'), array(array('in' => array(1,3)), array('like' => 'M%')));
属性映射到第二个条件,依此类推
由于这在 1.6 中被打破,我们可以使用 addFilter()
为多个属性指定简单的相等条件
例如:$col->addFilter('weight', 1, 'or')->addFilter('weight', 2, 'or')->addFilter('sku', 'ABC', 'or'); // weight is 1 or 2 or sku is ABC
您也可以始终使用$collection->getSelect()->orWhere(…)
,但您必须注意跨RDBMS兼容性
注意:这是我很久以前在tumblr上发布的内容的交叉帖子:
http://tweetorials.tumblr.com/post/10844018716/eav-collection-or-filtershttp://tweetorials.tumblr.com/post/11102525164/flat-table-collection-or-filters
宁愿不使用的解决方案,它通过Zend_Db方法修改 SELECT 语句。
$orderIds = Mage::getModel('sales/order')->getCollection()
->getSelect();
$adapter = $orderIds->getAdapter();
$quotedFrom = $adapter->quote(
$fromDate->toString('yyyy-MM-dd HH:mm:ss')
);
$quotedTo = $adapter->quote(
$toDate->toString('yyyy-MM-dd HH:mm:ss')
);
$orderIds
->where('status = ?', 'processing')
->where(
vsprintf(
'(created_at >= %s AND created_at <= %s)'
. ' OR (updated_at >= %s AND updated_at <= %s)',
array(
$quotedFrom, $quotedTo,
$quotedFrom, $quotedTo,
)
)
);
也许是时候在核心方面进行一些更改了。我们有一些类似的问题。也许情况是。
(条件 1) 或 ((条件 2) 和 (条件 3) .....
如果你对它是如何制作的感兴趣。尝试阅读http://winzter143.blogspot.com/2012/03/magento-hack-nested-addattributetofilte.html