addFilter बनाम addFieldToFilter


19

Magento संग्रह में फ़िल्टरिंग के दो तरीके हैं:

1. Varien_Data_Collection_Db::addFieldToFilter
2. Varien_Data_Collection::addFilter

ऐसा लगता है कि दोनों तरीकों को जोड़ने के लिए जहां हालत Zend_Db_Select। और क्या लाभ addFilterलाता है? इसके बजाय मुझे इसका उपयोग कब करना चाहिए addFieldToFilter?

जवाबों:


49

ठीक है, चलो उनकी जांच करते हैं। पहला अंतर यह है कि addFilter()अधिक सामान्य है और डेटाबेस विशिष्ट नहीं है। इसका उपयोग Varien_Directory_Collectionफ़ाइल नाम से फ़िल्टर करने के लिए भी किया जाता है । लेकिन इस जवाब के लिए मैं ध्यान केंद्रित करने जा रहा हूं Varien_Data_Collection_Db

उनके पास एक अलग हस्ताक्षर है, जहां addFilter यह कम लचीला लगता है, लेकिन आप देखेंगे कि इसके फायदे भी हैं:

1. addFieldToFilter ()

/**
 * Add field filter to collection
 *
 * @see self::_getConditionSql for $condition
 *
 * @param   string|array $field
 * @param   null|string|array $condition
 *
 * @return  Mage_Eav_Model_Entity_Collection_Abstract
 */
public function addFieldToFilter($field, $condition = null)

पैरामीटर

addFieldToFilter () स्थितियों की एक सरणी के साथ फ़ील्ड का एक सरणी ले सकते हैं, या एक एकल फ़ील्ड के साथ एक एकल स्थिति:

  • addFieldToFilter('field', 'value')

    का परिणाम: field=value

  • addFieldToFilter(['field1', 'field2'], ['value1', 'value2']);

    का परिणाम: field1=value1 OR field2=value2

प्रत्येक शर्त हो सकती है:

  • एक एकल अदिश मान (जैसे 'value1'और'value2' ऊपर)
  • फार्म में एक सरणी [ operator => value ]
  • Zend_Db_Expr वस्तु
  • शर्तों की एक सरणी जो "या" (हाँ, यह पुनरावर्ती है) के साथ संयुक्त है

यह, विशेष रूप से "ऑपरेटर => मान" सिंटैक्स को कोड में प्रलेखित किया गया है Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition()- यह याद रखें, मैं उन्हें अक्सर देखता हूं:

 * If $condition integer or string - exact value will be filtered ('eq' condition)
 *
 * If $condition is array - one of the following structures is expected:
 * - array("from" => $fromValue, "to" => $toValue)
 * - array("eq" => $equalValue)
 * - array("neq" => $notEqualValue)
 * - array("like" => $likeValue)
 * - array("in" => array($inValues))
 * - array("nin" => array($notInValues))
 * - array("notnull" => $valueIsNotNull)
 * - array("null" => $valueIsNull)
 * - array("moreq" => $moreOrEqualValue)
 * - array("gt" => $greaterValue)
 * - array("lt" => $lessValue)
 * - array("gteq" => $greaterOrEqualValue)
 * - array("lteq" => $lessOrEqualValue)
 * - array("finset" => $valueInSet)
 * - array("regexp" => $regularExpression)
 * - array("seq" => $stringValue)
 * - array("sneq" => $stringValue)
 *
 * If non matched - sequential array is expected and OR conditions
 * will be built using above mentioned structure

from/ toऑपरेटर में अतिरिक्त अनिर्दिष्ट सुविधा है :

  • साथ और['from' => $dateFrom, 'to' => $dateTo, 'date' => true]$dateFrom$dateTo मूल्यों दिनांक के रूप में पार्स किया जाएगा। वे किसी भी रूप में हो सकते हैं जिसे स्वीकार किया जाता हैVarien_Date::formatDate()
  • सुविधा को पार्स यदि आप तारीख की जरूरत है, लेकिन केवल में से एक तुलना करने के लिए <=या >=, आप छोड़ सकते हैं या तो 'from'या 'to'
  • 'datetime' => trueको भी काम करना चाहिए और समय को शामिल करना चाहिए, न केवल दिन, बल्कि वैरिएन_डब्‍लू_एडैप्टर_पेडो_मिस्कल में एक बग है : (लापता $includeTimestampपैरामीटर) जो datetimeउसी तरह काम करते हैं dateदोनों में समय शामिल है। तो अगर आप केवल दिनांक के आधार पर तुलना करने के लिए की जरूरत है, जोड़ने 00:00:00के लिए fromतिथि और 23:59:59करने के लिए toतारीख।

फील्ड मैपिंग

विधि फ़ील्ड मैपिंग का उपयोग करती है। फ़ील्ड मैपिंग को अन्य संग्रह नाम बनाने के लिए ठोस संग्रह कक्षाओं में परिभाषित किया जा सकता है। यहां उत्पाद संग्रह से एक उदाहरण दिया गया है:

protected $_map = array('fields' => array(
    'price'         => 'price_index.price',
    'final_price'   => 'price_index.final_price',
    'min_price'     => 'price_index.min_price',
    'max_price'     => 'price_index.max_price',
    'tier_price'    => 'price_index.tier_price',
    'special_price' => 'price_index.special_price',
));

2. AddFilter ()

/**
 * Add collection filter
 *s
 * @param string $field
 * @param string $value
 * @param string $type and|or|string
 */
public function addFilter($field, $value, $type = 'and')

पैरामीटर

addFilter()केवल एकल फ़ील्ड को एक मान और एक प्रकार से फ़िल्टर करने की अनुमति देता है । $typeइनमें से कोई भी हो सकता है:

  • "और" (डिफ़ॉल्ट) - जोड़ता है AND $field=$value WHERE क्लॉज में है (निश्चित रूप से उचित उद्धरण के साथ)
  • "या" - कहते हैं "OR $field=$value WHERE क्लॉज में है (ditto)
  • "स्ट्रिंग" - कहते हैं AND $value WHERE क्लॉज में जाता है (अर्थात $ मूल्य एक मनमाना SQL अभिव्यक्ति हो सकता है)
  • "सार्वजनिक" - फ़ील्ड मैपिंग और _getConditionSql(), के समान उपयोग करता हैaddFieldToFilter() । यह इसे लगभग शक्तिशाली बनाता है, यह केवल OR के साथ संयुक्त विभिन्न क्षेत्रों के लिए कई फिल्टर जोड़ने की सुविधा को याद कर रहा है।

में Varien_Data_Collection_Db::_renderFilters() आप देख सकते हैं कि वे किस तरह कार्रवाई की जाती है।

तानाना

एक महत्वपूर्ण अंतर है जो एक फायदा है addFilter()। यह फ़िल्टर को लागू करने के लिए एकत्र करता है $this->_filters()और Zend_Db_Selectसंग्रह को लोड करने से ठीक पहले उन्हें क्वेरी ऑब्जेक्ट में जोड़ता है ।addFieldToFilter()दूसरी ओर क्वेरी ऑब्जेक्ट को तुरंत हेरफेर करता है।

यह आपको उन फ़िल्टर को हेरफेर करने या हटाने की अनुमति देता है जो पहले से ही जोड़े गए हैं। वैरिएन संग्रह में इसके लिए एक इंटरफ़ेस नहीं है, आपको इसे अपने कस्टम संग्रह में लागू करना होगा। एक हुक विधि है _renderFiltersBefore()जिसे आप ओवरराइड कर सकते हैं।


मेरे पास एक प्रश्न है addFilterजिसका हम उपयोग कर सकते हैं attributes?
मुर्तुज़ा ज़बुवाला २५'१ Z शाम

@ मुर्तुजाअज़ुबाला नहीं, इसका उपयोग
ईएवी

इस उत्तर के लिए धन्यवाद फैबियन, मैंने इस बारे में आपकी वेबसाइट की पोस्ट का आनंद लिया, लेकिन एडफ़िल्टर में $ फ़ील्ड का क्या मूल्य हो सकता है? मैं केवल उन उत्पादों को फ़िल्टर करने के लिए addFilter फ़ंक्शन का उपयोग करने की कोशिश कर रहा हूं जो मॉड्यूल श्रेणी में चल रहे हैं
जॉन

AFAIK संभव नहीं है क्योंकि श्रेणियां एक विशेषता नहीं हैं, लेकिन एक अलग तालिका में उत्पादों से जुड़ी हैं। आपको मेरे सिर के ऊपर एक समाधान नहीं दे सकता, क्षमा करें
फेबियन शेंगलर

जवाब देने के लिए धन्यवाद, कोई चिंता नहीं, अगर मुझे एक रास्ता मिल जाए तो मैं इसे अपने समाधान के साथ यहां अपडेट करूंगा
जॉन

2

Magento संग्रह में अलग-अलग फ़िल्टर करने के दो तरीके हैं

  1. Varien_Data_Collection_Db :: addFieldToFilter

addFieldToFilter ($ फ़ील्ड, $ स्थिति = अशक्त)

का पहला पैरामीटर addFieldToFilterवह विशेषता है जिसे आप फ़िल्टर करना चाहते हैं। दूसरा वह मान है जिसकी आप तलाश कर रहे हैं। यहां हम skuमान के लिए एक फ़िल्टर जोड़ रहे हैं n2610

दूसरे पैरामीटर का उपयोग उस प्रकार को फ़िल्टर करने के लिए भी किया जा सकता है जिसे आप करना चाहते हैं। यह वह जगह है जहां चीजें थोड़ी जटिल हो जाती हैं, और थोड़ी अधिक गहराई के साथ जाने लायक हो जाती हैं।

तो डिफ़ॉल्ट रूप से, निम्नलिखित

$collection_of_products->addFieldToFilter('sku','n2610'); 

(अनिवार्य रूप से) के बराबर है

WHERE sku = "n2610"

आप खुद ही देख लें। निम्नलिखित चल रहा है

public function testAction()
{
    var_dump(
    (string) 
    Mage::getModel('catalog/product')
    ->getCollection()
    ->addFieldToFilter('sku','n2610')
    ->getSelect());
}

निकलेगा

SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'

ध्यान रखें, यदि आप एक ईएवी विशेषता का उपयोग कर रहे हैं, तो यह तेजी से जटिल हो सकता है। एक विशेषता जोड़ें

var_dump(
(string) 
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('meta_title','my title')
->getSelect()
);

और क्वेरी स्पष्ट रूप से हो जाती है।

SELECT `e`.*, IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) AS `meta_title` 
FROM `catalog_product_entity` AS `e` 
INNER JOIN `catalog_product_entity_varchar` AS `_table_meta_title_default` 
    ON (_table_meta_title_default.entity_id = e.entity_id) AND (_table_meta_title_default.attribute_id='103') 
    AND _table_meta_title_default.store_id=0        
LEFT JOIN `catalog_product_entity_varchar` AS `_table_meta_title` 
    ON (_table_meta_title.entity_id = e.entity_id) AND (_table_meta_title.attribute_id='103') 
    AND (_table_meta_title.store_id='1') 
WHERE (IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) = 'my title')

यदि आप समय सीमा पर हैं, तो इस बिंदु को विस्तृत न करें, लेकिन SQL के बारे में बहुत अधिक न सोचने का प्रयास करें।

अन्य तुलनात्मक ऑपरेटर मुझे यकीन है कि आप सोच रहे हैं "क्या होगा अगर मैं क्वेरी के बराबर के अलावा कुछ और चाहता हूं"? नहीं के बराबर, से अधिक, कम, आदि। AddFieldToFilter विधि के दूसरे पैरामीटर ने आपको वहां भी कवर किया है। यह एक वैकल्पिक वाक्यविन्यास का समर्थन करता है, जहां एक स्ट्रिंग में पास होने के बजाय, आप एक एकल तत्व ऐरे में पास होते हैं।

इस सरणी की कुंजी वह प्रकार है जिसकी आप तुलना करना चाहते हैं। उस कुंजी से जुड़ा मूल्य वह मान है जिसे आप फ़िल्टर करना चाहते हैं। चलो उपरोक्त फ़िल्टर को फिर से करें, लेकिन इस स्पष्ट सिंटैक्स के साथ

public function testAction()
{
    var_dump(
    (string) 
    Mage::getModel('catalog/product')
    ->getCollection()
    ->addFieldToFilter('sku',array('eq'=>'n2610'))
    ->getSelect()
    );          
}

हमारे फ़िल्टर को कॉल करना

addFieldToFilter('sku',array('eq'=>'n2610'))

जैसा कि आप देख सकते हैं, दूसरा पैरामीटर एक PHP सरणी है। इसकी कुंजी eq है, जो बराबर होती है। इस कुंजी का मान n2610 है, जो वह मान है जिसे हम फ़िल्टर कर रहे हैं।

Magento के पास इन अंग्रेजी भाषा के कई फिल्टर हैं जो दर्शकों में किसी भी पुराने पर्ल डेवलपर्स के लिए स्मरण (और शायद दर्द) का एक आंसू लाएंगे।

नीचे सूचीबद्ध सभी फ़िल्टर उनके SQL समकक्षों के उदाहरण के साथ हैं।

array("eq"=>'n2610')
WHERE (e.sku = 'n2610')

array("neq"=>'n2610')
WHERE (e.sku != 'n2610')

array("like"=>'n2610')
WHERE (e.sku like 'n2610')

array("nlike"=>'n2610')
WHERE (e.sku not like 'n2610')

array("is"=>'n2610')
WHERE (e.sku is 'n2610')

array("in"=>array('n2610'))
WHERE (e.sku in ('n2610'))

array("nin"=>array('n2610'))
WHERE (e.sku not in ('n2610'))

array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)

array("null"=>'n2610')
WHERE (e.sku is NULL)

array("gt"=>'n2610')
WHERE (e.sku > 'n2610')

array("lt"=>'n2610')
WHERE (e.sku < 'n2610')

array("gteq"=>'n2610')
WHERE (e.sku >= 'n2610')

array("moreq"=>'n2610') //a weird, second way to do greater than equal
WHERE (e.sku >= 'n2610')

array("lteq"=>'n2610')
WHERE (e.sku <= 'n2610')

array("finset"=>array('n2610'))
WHERE (find_in_set('n2610',e.sku))

array('from'=>'10','to'=>'20')
WHERE e.sku >= '10' and e.sku <= '20'

इनमें से अधिकांश आत्म व्याख्यात्मक हैं, लेकिन कुछ एक विशेष कॉलआउट के लायक हैं

में, नौ, find_in_set में और नौ सशर्त आप मूल्यों के एक सरणी में पारित करने के लिए अनुमति देते हैं। अर्थात्, आपके फ़िल्टर सरणी का मान भाग स्वयं एक सरणी होने की अनुमति है।

array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))

notnull, null SQL के अधिकांश फ्लेवर में कीवर्ड NULL विशेष है। यह आमतौर पर मानक समानता (=) ऑपरेटर के साथ अच्छा नहीं खेलेगा। आपके फ़िल्टर प्रकार के रूप में नोटनल या नल को निर्दिष्ट करना, जो भी आपके द्वारा पास किए गए मूल्य को अनदेखा करते हुए आपको NULL तुलना के लिए सही सिंटैक्स प्राप्त करेगा।

array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)

से - फ़िल्टर करने के लिए यह एक और विशेष प्रारूप है जो मानक नियम को तोड़ता है। एक एकल तत्व सरणी के बजाय, आप दो तत्व सरणी निर्दिष्ट करते हैं। एक तत्व की कुंजी है, दूसरे तत्व की कुंजी है। संकेतित कुंजियों के रूप में, यह फ़िल्टर आपको प्रतीकों से अधिक और कम के बारे में चिंता किए बिना / से लेकर रेंज तक निर्माण करने की अनुमति देता है

public function testAction
{
        var_dump(
        (string) 
        Mage::getModel('catalog/product')
        ->getCollection()
        ->addFieldToFilter('price',array('from'=>'10','to'=>'20'))
        ->getSelect()
        );                      
}

उपरोक्त पैदावार

WHERE (_table_price.value >= '10' and _table_price.value <= '20')'

और या या, या वह और है? अंत में, हम बूलियन ऑपरेटरों के पास आते हैं। यह दुर्लभ क्षण है जहां हम केवल एक विशेषता द्वारा फ़िल्टर कर रहे हैं। सौभाग्य से, Magento के संग्रह हमें कवर किया है। आप “और” प्रश्नों की संख्या प्राप्त करने के लिए AddFieldToFilter में कई कॉल को एक साथ चेन कर सकते हैं।

function testAction()
{
        echo(
        (string) 
        Mage::getModel('catalog/product')
        ->getCollection()
        ->addFieldToFilter('sku',array('like'=>'a%'))
        ->addFieldToFilter('sku',array('like'=>'b%'))
        ->getSelect()
        );                                  
}

उपरोक्त के रूप में कई कॉल को एक साथ जोड़कर, हम एक क्लॉज उत्पन्न करेंगे जो निम्नलिखित की तरह कुछ दिखता है

WHERE (e.sku like 'a%') AND (e.sku like 'b%')

आप में से जो सिर्फ अपना हाथ बढ़ाते हैं, हां, उपरोक्त उदाहरण हमेशा 0 रिकॉर्ड लौटाएगा। कोई भी स्कोल BOTH a और a से शुरू नहीं हो सकता है। हम शायद यहाँ एक OR क्वेरी चाहते हैं। यह हमें AddFieldToFilter के दूसरे पैरामीटर के एक और भ्रामक पहलू पर लाता है।

यदि आप OR क्वेरी बनाना चाहते हैं, तो आपको दूसरे पैरामीटर के रूप में एक Array of filter Arrays पास करना होगा। मुझे लगता है कि अपने व्यक्तिगत फ़िल्टर एरेज़ को वेरिएबल्स में असाइन करना सबसे अच्छा है

public function testAction()
{
        $filter_a = array('like'=>'a%');
        $filter_b = array('like'=>'b%');
}

और फिर मेरे सभी फ़िल्टर चर की एक सरणी असाइन करें

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

स्पष्ट होने के हित में, यहाँ फ़िल्टर एरे का पूर्वोक्त ऐरे है।

array($filter_a,$filter_b)

यह हमें एक WHERE क्लॉज देगा जो निम्नलिखित की तरह कुछ दिखता है

WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
  1. Varien_Data_Collection :: addFilter
 addFilter($field, $value, $type = 'and')

addFilter()केवल एकल फ़ील्ड को एक मान और एक प्रकार से फ़िल्टर करने की अनुमति देता है। $typeइनमें से कोई भी हो सकता है:

  1. "और" (डिफ़ॉल्ट) - जहां और $ क्षेत्र = $ मूल्य जहां क्लॉज के लिए
  2. "या" - "$ $ फ़ील्ड = $ मान को जहां क्लॉज में जोड़ता है"

अधिक विवरण देखें


1
यह कुछ भी स्पष्ट नहीं करता है।
फेबियन शेंगलर

इसका कोई मतलब नहीं है। यह इन विधियों के अंतर का वर्णन नहीं करता है
लिंडर


2
आपका अद्यतन उत्तर अधिकतर alanstorm.com/magento_collections से कॉपी किया गया है । कृपया कम से कम अपने स्रोतों का हवाला दें!
फाबियन शेंगलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.