2012-06-15 49 views
9

你如何通過ATTRIBUTE1 =值過濾Magento的銷售訂單集合(attribute2 =數值或attribute3 =值2)?我可以寫WHERE {COND1}和{COND2}或{} COND3,但我不能組AND({COND2}或{} COND3)過濾Magento的類別由COND1 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' 

在通過代碼挖掘,我發現的addFieldToFilter功能在LIB /瓦瑞恩/數據/收集/ 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; 
}  

它看起來像用於接受所述第一參數爲一個數組addFieldToFilter,但沒有w ^它必須是一個字符串......有趣,所以我試圖用零運氣以下...

$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嘗試和錯誤消息是「無法確定字段名」。


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; 
} 

當我更新我的代碼,我得到非常接近我想要的結果,但我真正想要的是有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') 
+0

我不認爲你能做到這一點,因爲'銷售/ order'映射到一個平坦的TA BLE。取而代之的是使用getSelect()。 – nevvermind

+0

@nevvermind爲什麼它應該不管它是不是一張桌子? – nachito

+1

它不應該。 http://stackoverflow.com/a/5245895/394589 – nevvermind

回答

0

這裏是解決方案,我寧可不使用,它通過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, 
      ) 
     ) 
    ); 
2

請注意,FLAT TABLE和EAV集合使用不同的語法!

添加或條件EAV集合

注意,對於同一屬性指定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濾波器用於不同的屬性:只能傳遞一個參數,使用屬性條件的陣列。

添加或條件FLAT TABLE集合

指定一個OR與在平坦的表集的單個屬性過濾相同上的EAV集合。

例如:$col->addFieldToFilter('name', array(array('like' => 'M%'), array('like' => '%O'))); // get items whose name start with M OR end with O

要加入的多個屬性在一個或病症的語法是從EAV集合不同(注意:這是在Magento 1.6 BROKEN):$col->addFieldToFilter(array('weight', 'name'), array(array('in' => array(1,3)), array('like' => 'M%')));

第一屬性

例如被映射到第一個條件,第二個屬性被映射到第二個條件,等等。

因爲這在1.6中被打破了,所以我們可以指定簡單的EQU使用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兼容性

注:這是thwo東西跨崗位我張貼年齡前的tumblr:
http://tweetorials.tumblr.com/post/10844018716/eav-collection-or-filters
http://tweetorials.tumblr.com/post/11102525164/flat-table-collection-or-filters

相關問題