【发布时间】:2012-06-15 18:04:48
【问题描述】:
如何通过 attribute1 = value1 AND (attribute2 = value2 OR attribute3 = value2) 过滤 Magento 销售订单集合?我可以写 WHERE {COND1} AND {COND2} OR {COND3},但我不能组合 AND ({COND2} OR {COND3})
首先,这不是重复的 AFAIK,我见过 this,它在 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.php 中找到了 addFieldToFilter 函数
/**
* 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 AND (CONDITION2 OR 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')
【问题讨论】:
-
我不认为你可以这样做,因为
sales/order映射到一个平面表。改为在集合上使用 getSelect()。 -
@nevvermind 为什么它是否是平桌很重要?
-
@nevvermind 很好的参考。我在搜索中从未遇到过那个 Q。我仍然希望有办法做到这一点,但有趣的是 sales_order 表在 1.3.2 中是 EAV,现在是平面表。