Odpowiedzi:
OK, sprawdźmy je. Pierwszą różnicą jest to, że addFilter()
jest bardziej ogólna, a nie specyficzna dla bazy danych. Służy również Varien_Directory_Collection
do filtrowania według nazwy pliku. Ale na tę odpowiedź zamierzam się skupić Varien_Data_Collection_Db
.
Metody te mają inną sygnaturę, która addFilter
wydaje się mniej elastyczna, ale zobaczysz, że ma ona również swoje zalety:
/**
* 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 () może przyjmować tablicę pól z tablicą warunków lub pojedyncze pole z jednym warunkiem:
addFieldToFilter('field', 'value')
Prowadzi do: field=value
addFieldToFilter(['field1', 'field2'], ['value1', 'value2']);
Prowadzi do: field1=value1 OR field2=value2
Każdy warunek może być:
'value1'
i 'value2'
powyżej)[ operator => value ]
Zend_Db_Expr
przedmiotTa, zwłaszcza składnia „operator => wartość” jest udokumentowana w kodzie pod adresem Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition()
- pamiętaj o tym, często je sprawdzam:
* 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
Istnieje dodatkowa nieudokumentowana funkcja w from
/ to
operator:
['from' => $dateFrom, 'to' => $dateTo, 'date' => true]
$dateFrom
$dateTo
wartości będą przetwarzane tak terminach. Mogą być w dowolnej formie zaakceptowanej przezVarien_Date::formatDate()
<=
lub >=
można pominąć albo 'from'
albo 'to'
.'datetime' => true
ma również działać i uwzględniać czas, nie tylko dzień, ale jest błąd w Varien_Db_Adapter_Pdo_Mysql :: _ preparSqlDateCondition () (brak $includeTimestamp
parametru), który sprawia, że datetime
działa tak samo jak date
. Oba obejmują czas. Więc jeśli trzeba porównać tylko według daty, dodać 00:00:00
do from
daty i 23:59:59
do to
tej pory.Metoda wykorzystuje mapowanie pól. Odwzorowania pól można zdefiniować w konkretnych klasach kolekcji, aby utworzyć aliasy nazw pól. Oto przykład z kolekcji produktów:
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',
));
/**
* Add collection filter
*s
* @param string $field
* @param string $value
* @param string $type and|or|string
*/
public function addFilter($field, $value, $type = 'and')
addFilter()
pozwala tylko na filtrowanie pojedynczego pola według pojedynczej wartości i typu . $type
może być dowolnym z:
AND $field=$value
do klauzuli WHERE (oczywiście z prawidłowym cytowaniem)"OR $field=$value
do klauzuli WHERE (podobnie)AND $value
do klauzuli WHERE (tzn. wartość $ może być dowolnym wyrażeniem SQL)_getConditionSql()
podobnie jak addFieldToFilter()
. To sprawia, że jest prawie tak samo wydajny, brakuje tylko funkcji dodawania wielu filtrów dla różnych pól w połączeniu z OR.W Varien_Data_Collection_Db::_renderFilters()
można zobaczyć w jaki sposób są one przetwarzane.
Jest jedna ważna różnica, która jest zaletą addFilter()
. Zbiera filtry, które mają zostać zastosowane, $this->_filters()
i dodaje je tylko do Zend_Db_Select
obiektu zapytania tuż przed załadowaniem kolekcji. addFieldToFilter()
z drugiej strony natychmiast manipuluje obiektem zapytania.
Umożliwia to manipulowanie lub usuwanie filtrów, które zostały już dodane. Kolekcja Varien nie ma dla niej interfejsu, musisz zaimplementować to w swojej kolekcji niestandardowej. Istnieje metoda haka _renderFiltersBefore()
, którą można zastąpić.
Kolekcja Magento ma dwie metody filtrowania poniżej
- Varien_Data_Collection_Db :: addFieldToFilter
addFieldToFilter ($ field, $ condition = null)
Pierwszy parametr addFieldToFilter
to atrybut, według którego chcesz filtrować. Druga to wartość, której szukasz. Oto dodajemy sku
filtr wartości n2610
.
Drugi parametr może być również użyty do określenia rodzaju filtrowania, które chcesz wykonać. W tym miejscu sprawy stają się trochę skomplikowane i warto je zagłębić nieco głębiej.
Więc domyślnie następujące
$collection_of_products->addFieldToFilter('sku','n2610');
jest (zasadniczo) równoważny z
WHERE sku = "n2610"
Sprawdź sam. Uruchamianie następujących
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku','n2610')
->getSelect());
}
ustąpi
SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'
Pamiętaj, że może to szybko się skomplikować, jeśli używasz atrybutu EAV. Dodaj atrybut
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('meta_title','my title')
->getSelect()
);
i zapytanie staje się niepoprawne.
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')
Nie spiesz się, ale staraj się nie myśleć za dużo o SQL, jeśli dotrzymasz terminu.
Inne operatory porównania Jestem pewien, że zastanawiasz się „co jeśli chcę czegoś innego niż równa się zapytaniem”? Nie równy, większy niż, mniejszy itp. Drugi parametr metody addFieldToFilter również tam uwzględniał. Obsługuje alternatywną składnię, w której zamiast przekazywać ciąg, przekazujesz pojedynczy element Array.
Kluczem tej tablicy jest rodzaj porównania, które chcesz wykonać. Wartość powiązana z tym kluczem to wartość, według której chcesz filtrować. Ponówmy powyższy filtr, ale z tą jawną składnią
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('eq'=>'n2610'))
->getSelect()
);
}
Wywoływanie naszego filtra
addFieldToFilter('sku',array('eq'=>'n2610'))
Jak widać, drugim parametrem jest tablica PHP. Jego kluczem jest eq, co oznacza równość. Wartość tego klucza to n2610, czyli wartość, którą filtrujemy.
Magento ma wiele takich anglojęzycznych filtrów, które przyniosą łzę pamięci (i być może bólu) wszystkim starym programistom Perla na widowni.
Poniżej wymienione są wszystkie filtry wraz z przykładem ich odpowiedników 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'
Większość z nich jest oczywista, ale kilka zasługuje na specjalne objaśnienie
in, nin, find_in_set Warunki warunkowe in i nin pozwalają przekazać tablicę wartości. Oznacza to, że część wartości tablicy filtrów może sama być tablicą.
array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))
notnull, null Słowo kluczowe NULL jest wyjątkowe w większości odmian SQL. Zwykle nie gra dobrze ze standardowym operatorem równości (=). Podanie notnull lub null jako typu filtru zapewni poprawną składnię dla porównania NULL, ignorując przy tym jakąkolwiek przekazywaną wartość
array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)
from - to filter Jest to kolejny specjalny format, który łamie standardową regułę. Zamiast tablicy z jednym elementem określasz tablicę z dwoma elementami. Jeden element ma klucz, a drugi ma klucz do. Jak wskazano na kluczach, ten filtr pozwala konstruować zakres od / do bez martwienia się o symbole większe i mniejsze niż
public function testAction
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('price',array('from'=>'10','to'=>'20'))
->getSelect()
);
}
Powyższe daje
WHERE (_table_price.value >= '10' and _table_price.value <= '20')'
AND lub OR, czy to jest OR i AND? Wreszcie dochodzimy do operatorów boolowskich. To rzadki moment, w którym filtrujemy tylko według jednego atrybutu. Na szczęście kolekcje Magento nas obejmują. Możesz połączyć wiele połączeń w addFieldToFilter, aby uzyskać szereg zapytań „ORAZ”.
function testAction()
{
echo(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('like'=>'a%'))
->addFieldToFilter('sku',array('like'=>'b%'))
->getSelect()
);
}
Łącząc ze sobą wiele wywołań, jak powyżej, stworzymy klauzulę where, która wygląda mniej więcej tak:
WHERE (e.sku like 'a%') AND (e.sku like 'b%')
Dla tych z was, którzy właśnie podnieśli rękę, tak, powyższy przykład zawsze zwróci 0 rekordów. Żadne SKU nie może zaczynać się od OBA i a i b. Prawdopodobnie chcemy tutaj zapytania OR. To prowadzi nas do kolejnego mylącego aspektu drugiego parametru addFieldToFilter.
Jeśli chcesz zbudować zapytanie OR, musisz przekazać tablicę tablic filtrów jako drugi parametr. Uważam, że najlepiej przypisać indywidualne tablice filtrów do zmiennych
public function testAction()
{
$filter_a = array('like'=>'a%');
$filter_b = array('like'=>'b%');
}
a następnie przypisz tablicę wszystkich moich zmiennych filtrów
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()
);
}
Dla jasności, oto wspomniana tablica tablic filtrujących.
array($filter_a,$filter_b)
To da nam klauzulę WHERE, która wygląda mniej więcej tak:
WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
- Varien_Data_Collection :: addFilter
addFilter($field, $value, $type = 'and')
addFilter()
pozwala tylko na filtrowanie pojedynczego pola według pojedynczej wartości i typu. $type
może być dowolnym z:
addFilter
zattributes
?