addFilter ve addFieldToFilter karşılaştırması


19

Magento koleksiyonunun iki filtreleme yöntemi vardır:

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

Her iki yöntemin nereye koşul eklediğini görünüyor Zend_Db_Select. Ve ne gibi avantajlar addFiltergetiriyor? Ne zaman kullanmalıyım addFieldToFilter?

Yanıtlar:


49

Tamam, bunları inceleyelim. İlk fark, addFilter()veritabanına özgü değil, daha genel olmasıdır. Varien_Directory_CollectionDosya adına göre filtrelemek için de kullanılır . Ama bu cevap için odaklanacağım Varien_Data_Collection_Db.

Yöntemlerin addFilterdaha az esnek gibi göründüğü farklı bir imzası vardır, ancak bunun da avantajları olduğunu göreceksiniz:

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)

Parametreler

addFieldToFilter (), bir dizi koşul içeren bir alan dizisini veya tek bir koşulu olan tek bir alanı alabilir:

  • addFieldToFilter('field', 'value')

    Sonuçlar: field=value

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

    Sonuçlar: field1=value1 OR field2=value2

Her koşul şöyle olabilir:

  • tek bir skaler değer (gibi 'value1've 'value2'üstü)
  • formdaki bir dizi [ operator => value ]
  • bir Zend_Db_Exprnesne
  • "VEYA" ile birleştirilen bir dizi koşul (evet, bu özyinelemeli)

Bu, özellikle "operatör => değer" sözdizimi kodu belgelenmiştir Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition()- bunu unutmayın, oldukça sık onları aramak:

 * 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/ toOperatöründe ek belgelenmemiş özellik var :

  • ile ve değerler tarihleri olarak ayrıştırılır. Tarafından kabul edilen herhangi bir biçimde olabilirler.['from' => $dateFrom, 'to' => $dateTo, 'date' => true]$dateFrom$dateToVarien_Date::formatDate()
  • tarih gerekirse özelliği ayrıştırma ama sadece birini karşılaştırmak <=ya >=, ya atlayabilirsiniz 'from'ya 'to'.
  • 'datetime' => trueçok çalışmalı ve sadece günü değil zamanı da içermelidir , ancak Varien_Db_Adapter_Pdo_Mysql :: _ preparSqlDateCondition () 'da (eksik $includeTimestampparametre) datetimeçalışmayı aynı şekilde yapan bir hata vardır date. Her ikisi de zamanı içerir. Yalnızca tarihe göre karşılaştırmak gerekirse, ekleme 00:00:00için fromtarih ve 23:59:59hiç totarih.

Alan eşleme

Yöntemde alan eşleme kullanılır. Alan eşlemeleri, takma ad alan adları oluşturmak için somut toplama sınıflarında tanımlanabilir. İşte ürün koleksiyonundan bir örnek:

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')

Parametreler

addFilter()yalnızca tek bir alanı tek bir değere ve türe göre filtrelemeye izin verir . $typeşunlardan herhangi biri olabilir:

  • "ve" (varsayılan) - AND $field=$valueWHERE yantümcesine ekler (elbette uygun alıntılarla)
  • "veya" - "OR $field=$valueWHERE yantümcesine ekler (ditto)
  • "string" - AND $valueWHERE yantümcesine ekler (yani, $ değeri isteğe bağlı bir SQL ifadesi olabilir)
  • "genel" - alan eşlemeyi kullanır ve _getConditionSql()benzeri addFieldToFilter(). Bu neredeyse onu güçlü yapar, sadece OR ile birlikte farklı alanlar için birden fazla filtre ekleme özelliği yoktur.

İçinde Varien_Data_Collection_Db::_renderFilters() nasıl işlendiğini görebilirsiniz.

uzayabilirlik

Avantajlı olan önemli bir fark vardır addFilter(). Uygulanacak filtreleri toplar $this->_filters()ve yalnızca Zend_Db_Selectkoleksiyonu yüklemeden hemen önce sorgu nesnesine ekler . addFieldToFilter()diğer yandan, sorgu nesnesini hemen manipüle eder.

Bu, önceden eklenmiş filtreleri değiştirmenize veya kaldırmanıza olanak tanır. Varien koleksiyonunun bunun için bir arayüzü yok, bunu özel koleksiyonunuza uygulamalısınız. _renderFiltersBefore()Geçersiz kılabileceğiniz bir kanca yöntemi vardır.


Kullanabileceğimiz tek bir sorum addFiltervar attributes?
Murtuza Zabuawala

@MurtuzaZabuawala hayır, EAV özellikleri için kullanılamaz
Fabian Schmengler

Bu cevap için teşekkür ederiz Fabian, web sitenizin bu konudaki mesajını da beğendim, ancak addFilter'de $ field hangi değeri tutabilir? sadece modül çalışıyor kategorisinde olan ürünleri filtrelemek için addFilter işlevini kullanmaya çalışıyorum
John

Kategoriler nitelikler değil, ayrı bir tablodaki ürünlerle ilişkili olduğundan AFAIK mümkün değildir. Sana kafamın üstünde bir çözüm veremem, üzgünüm
Fabian Schmengler

Yanıt verdiğiniz için teşekkürler, endişelenmeyin, bir yol bulursam burada
John

2

Magento koleksiyonunda farklı körük filtreleme için iki yöntem vardır

  1. Varien_Data_Collection_Db :: addFieldToFilter

addFieldToFilter ($ field, $ condition = null)

Öğesinin ilk parametresi, addFieldToFilterfiltrelemek istediğiniz özelliktir. İkincisi, aradığınız değerdir. İşte skudeğer için bir filtre ekliyoruz n2610.

İkinci parametre, yapmak istediğiniz filtreleme türünü belirtmek için de kullanılabilir. Bu, işlerin biraz karmaşıklaştığı ve biraz daha derinlemesine girmeye değer olduğu yerdir.

Yani varsayılan olarak aşağıdakiler

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

(esasen) eşittir

WHERE sku = "n2610"

Kendinize bir bakın. Aşağıdakileri çalıştırma

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

getirecek

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

Bir EAV özniteliği kullanıyorsanız bunun hızlı bir şekilde karmaşık olabileceğini unutmayın. Özellik ekle

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

ve sorgu gnarly alır.

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')

Konuyu işaretlemek değil, ancak son tarihte iseniz SQL hakkında çok fazla düşünmemeye çalışın.

Diğer Karşılaştırma Operatörleri “Sorguya eşit bir şeyden başka bir şey istiyorsam” diye merak ettiğinizden eminim? Eşit değil, büyük, küçük, vb. AddFieldToFilter yönteminin ikinci parametresi orada da sizi kapsıyor. Alternatif bir sözdizimini destekler; burada, bir dize geçirmek yerine tek bir öğe Dizi geçirirsiniz.

Bu dizinin anahtarı yapmak istediğiniz karşılaştırma türüdür. Bu anahtarla ilişkilendirilen değer, filtrelemek istediğiniz değerdir. Yukarıdaki filtreyi tekrar yapalım, ancak bu açık sözdizimiyle

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

Filtremizi çağırmak

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

Gördüğünüz gibi, ikinci parametre bir PHP Dizisidir. Onun anahtarı eşittir, eşittir. Bu anahtarın değeri, filtrelediğimiz değer olan n2610'dur.

Magento, izleyicideki eski perl geliştiricilerine bir hatırlama gözyaşı (ve belki de acı) getirecek filtreler gibi bu İngiliz dilinden bir dizi var.

Aşağıda, SQL eşdeğerlerinin bir örneği ile birlikte tüm filtreler listelenmiştir.

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'

Bunların çoğu kendinden açıklayıcıdır, ancak birkaçı özel bir belirtmeyi hak ediyor

in, nin, find_in_set in ve nin koşulları bir değerler dizisi geçirmenize izin verir. Yani, filtre dizinizin değer bölümünün kendisinin bir dizi olmasına izin verilir.

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

notnull, null NULL anahtar sözcüğü SQL'in çoğu çeşidinde özeldir. Genellikle standart eşitlik (=) operatörü ile iyi oynamaz. Filtre türünüz olarak null veya null belirtmek, ilettiğiniz değeri göz ardı ederken size NULL karşılaştırma için doğru sözdizimini sağlar.

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

from - to filter Bu, standart kuralı ihlal eden başka bir özel biçimdir. Tek bir eleman dizisi yerine iki elemanlı bir dizi belirtirsiniz. Bir öğenin anahtarı, diğer öğenin anahtarı vardır. Anahtarların belirttiği gibi, bu filtre sembollerden daha büyük ve daha az endişelenmenize gerek kalmadan bir / aralığında aralığı oluşturmanıza izin verir

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

Yukarıdaki verimler

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

VE veya VEYA, ya da VEYA VE VE mı? Sonunda, boole operatörlerine geldik. Sadece bir özelliğe göre filtrelediğimiz nadir an. Neyse ki, Magento'nun Koleksiyonları bizi ele aldı. Bir dizi “AND” sorgusu almak için addFieldToFilter için birden çok çağrıyı birbirine zincirleyebilirsiniz.

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

Yukarıdaki gibi birden fazla çağrıyı birbirine bağlayarak, aşağıdakine benzer bir yerde yan tümcesi üreteceğiz

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

Elinizi kaldırmış olanlarınız için, evet, yukarıdaki örnek her zaman 0 kayıt döndürür. Hiçbir sku İKİ a ve b ile başlayamaz. Muhtemelen burada istediğimiz bir OR sorgusudur. Bu bizi addFieldToFilter'ın ikinci parametresinin başka bir kafa karıştırıcı yönüne getiriyor.

Bir OR sorgusu oluşturmak istiyorsanız, ikinci parametre olarak bir filtre dizisi dizisi iletmeniz gerekir. Bireysel filtre Dizilerinizi değişkenlere atamanın en iyisi olduğunu düşünüyorum

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

ve sonra tüm filtre değişkenlerimden bir dizi ata

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

Açık olmak adına, yukarıda sözü edilen filtre dizileri dizisi.

array($filter_a,$filter_b)

Bu bize aşağıdakine benzer bir WHERE yantümcesi verecektir.

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

addFilter()yalnızca tek bir alanı tek bir değere ve türe göre filtrelemeye izin verir. $typeşunlardan herhangi biri olabilir:

  1. "ve" (varsayılan) - WHERE yan tümcesine AND $ field = $ değerini ekler
  2. "veya" - WHERE deyimine "OR $ field = $ değer ekler"

Daha Fazla Ayrıntıya Bakın


1
Bu hiçbir şeyi açıklamaz.
Fabian Schmengler

Bu hiç mantıklı değil. Bu yöntemlerin farkını tanımlamıyor
Lindar


2
Güncel cevabınız çoğunlukla alanstorm.com/magento_collections adresinden kopyalanır . Lütfen kaynaklarınızı en azından belirtiniz!
Fabian Schmengler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.