通过COND1和(COND2或COND3)过滤Magento集合

nac*_*ito 9 php mysql magento

如何通过attribute1 = value1 AND(attribute2 = value2 OR attribute3 = value2)过滤Magento销售订单集合?我可以写WHERE {COND1} AND {COND2}或{COND3},但我不能分组AND({COND2} OR {COND3})

首先,这不是一个重复的AFAIK,我已经看到了,它在版本1.3.2中运行良好,但在Enterprise Edition 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'),
        ),
    ));
Run Code Online (Sandbox Code Playgroud)

这是它生成的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' 
Run Code Online (Sandbox Code Playgroud)

在挖掘代码时,我addFieldToFilter在lib/Varien/Data/Collection/Db.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;
}       
Run Code Online (Sandbox Code Playgroud)

它看起来像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')
))
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过操纵SQL来做到这一点,但我真的想知道怎么做"Magento方式"如果有的话......

顺便说一句,我也尝试使用addAttributeToFilter,错误信息是"无法确定字段名称".


UPDATE

我发现了两个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;
}
Run Code Online (Sandbox Code Playgroud)

当我更新我的代码时,我非常接近我想要的结果,但我真正想要的是拥有CONDITION1 AND(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')
Run Code Online (Sandbox Code Playgroud)

nac*_*ito 1

这是我不想使用的解决方案,它通过 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,
            )
        )
    );
Run Code Online (Sandbox Code Playgroud)