Risposte:
OK, esaminiamoli. La prima differenza è che addFilter()
è più generico e non specifico del database. Viene anche utilizzato da Varien_Directory_Collection
per filtrare in base al nome del file. Ma per questa risposta mi concentrerò su Varien_Data_Collection_Db
.
I metodi hanno una firma diversa, dove addFilter
sembra essere meno flessibile, ma vedrai che ha anche i suoi vantaggi:
/**
* 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 () può accettare una matrice di campi con una matrice di condizioni o un singolo campo con una singola condizione:
addFieldToFilter('field', 'value')
Risultati in: field=value
addFieldToFilter(['field1', 'field2'], ['value1', 'value2']);
Risultati in: field1=value1 OR field2=value2
Ogni condizione può essere:
'value1'
e 'value2'
sopra)[ operator => value ]
Zend_Db_Expr
oggettoQuesta, in particolare la sintassi "operator => value" è documentata nel codice su Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition()
- ricordate questo, li guardo abbastanza spesso:
* 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
C'è un'altra funzione non documentata nell'operatore from
/ to
:
['from' => $dateFrom, 'to' => $dateTo, 'date' => true]
i valori $dateFrom
e $dateTo
verranno analizzati come date. Possono essere in qualsiasi forma accettata daVarien_Date::formatDate()
<=
o >=
, puoi omettere 'from'
o 'to'
.'datetime' => true
dovrebbe funzionare anche e includere l'ora, non solo il giorno, ma c'è un bug in Varien_Db_Adapter_Pdo_Mysql :: _ preparSqlDateCondition () ( $includeTimestamp
parametro mancante ) che fa datetime
funzionare allo stesso modo di date
. Entrambi includono il tempo. Quindi, se devi confrontare solo per data, aggiungi 00:00:00
alla from
data e 23:59:59
alla to
data.Il metodo utilizza la mappatura dei campi. I mapping dei campi possono essere definiti in classi di raccolta concrete per creare nomi di campi alias. Ecco un esempio dalla collezione di prodotti:
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()
consente di filtrare un singolo campo solo per un singolo valore e a tipo . $type
può essere uno dei seguenti:
AND $field=$value
alla clausola WHERE (ovviamente con la citazione corretta)"OR $field=$value
alla clausola WHERE (idem)AND $value
alla clausola WHERE (ovvero $ value può essere un'espressione SQL arbitraria)_getConditionSql()
, in modo simile aaddFieldToFilter()
. Questo lo rende quasi altrettanto potente, manca solo la funzione di aggiungere più filtri per diversi campi combinati con OR.Nel Varien_Data_Collection_Db::_renderFilters()
puoi vedere come vengono elaborati.
C'è una differenza importante per cui è un vantaggio addFilter()
. Raccoglie i filtri da applicare $this->_filters()
e li aggiunge solo Zend_Db_Select
all'oggetto query subito prima di caricare la raccolta.addFieldToFilter()
d'altra parte manipola immediatamente l'oggetto query.
Ciò consente di manipolare o rimuovere i filtri che sono già stati aggiunti. La collezione Varien non ha un'interfaccia per essa, devi implementarla nella tua collezione personalizzata. C'è un metodo hook _renderFiltersBefore()
che puoi ignorare.
La collezione Magento ha due metodi per filtrare qui sotto diversi
- Varien_Data_Collection_Db :: addFieldToFilter
addFieldToFilter ($ field, $ condition = null)
Il primo parametro di addFieldToFilter
è l'attributo per cui si desidera filtrare. Il secondo è il valore che stai cercando. Qui stiamo aggiungendo un sku
filtro per il valore n2610
.
Il secondo parametro può essere utilizzato anche per specificare il tipo di filtro che si desidera eseguire. È qui che le cose si complicano e vale la pena approfondire un po 'di più.
Quindi, per impostazione predefinita, il seguente
$collection_of_products->addFieldToFilter('sku','n2610');
è (essenzialmente) equivalente a
WHERE sku = "n2610"
Dai un'occhiata a te stesso. In esecuzione il seguente
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku','n2610')
->getSelect());
}
cederà
SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'
Tieni presente che ciò può complicarsi rapidamente se stai utilizzando un attributo EAV. Aggiungi un attributo
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('meta_title','my title')
->getSelect()
);
e la query diventa nodosa.
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')
Non ribadire il punto, ma cerca di non pensare troppo all'SQL se sei in scadenza.
Altri operatori di confronto Sono sicuro che ti starai chiedendo "cosa succede se desidero qualcosa di diverso da un uguale per query"? Non uguale, maggiore di, minore di, ecc. Anche il secondo parametro del metodo addFieldToFilter ti ha coperto. Supporta una sintassi alternativa in cui, invece di passare una stringa, si passa in un singolo elemento Array.
La chiave di questo array è il tipo di confronto che si desidera effettuare. Il valore associato a quella chiave è il valore per cui si desidera filtrare. Ripeti il filtro sopra, ma con questa sintassi esplicita
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('eq'=>'n2610'))
->getSelect()
);
}
Richiamo del nostro filtro
addFieldToFilter('sku',array('eq'=>'n2610'))
Come puoi vedere, il secondo parametro è un array PHP. La sua chiave è l'eq, che sta per uguali. Il valore per questa chiave è n2610, che è il valore su cui stiamo filtrando.
Magento ha una serie di questi filtri in lingua inglese che porteranno una lacrima di ricordo (e forse di dolore) a qualsiasi vecchio sviluppatore di perl nel pubblico.
Di seguito sono elencati tutti i filtri, insieme a un esempio dei loro equivalenti 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'
La maggior parte di questi sono autoesplicativi, ma alcuni meritano un callout speciale
in, nin, find_in_set I condizionali in e nin consentono di passare una matrice di valori. Cioè, la porzione di valore dell'array di filtri può essere essa stessa un array.
array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))
notnull, null La parola chiave NULL è speciale nella maggior parte dei tipi di SQL. In genere non funziona bene con l'operatore di uguaglianza standard (=). Specificando notnull o null come tipo di filtro otterrai la sintassi corretta per un confronto NULL ignorando qualunque valore passi
array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)
da - a filtro Questo è un altro formato speciale che infrange la regola standard. Invece di una matrice a singolo elemento, si specifica una matrice a due elementi. Un elemento ha la chiave da, l'altro elemento ha la chiave a. Come indicato dai tasti, questo filtro consente di costruire un intervallo da / a senza preoccuparsi dei simboli maggiore o minore dei simboli
public function testAction
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('price',array('from'=>'10','to'=>'20'))
->getSelect()
);
}
I rendimenti di cui sopra
WHERE (_table_price.value >= '10' and _table_price.value <= '20')'
AND o OR oppure OR e AND? Infine, arriviamo agli operatori booleani. È il raro momento in cui filtriamo solo per un attributo. Fortunatamente, le Collezioni di Magento ci hanno coperto. È possibile concatenare più chiamate a addFieldToFilter per ottenere un numero di query "AND".
function testAction()
{
echo(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('like'=>'a%'))
->addFieldToFilter('sku',array('like'=>'b%'))
->getSelect()
);
}
Concatenando più chiamate come sopra, creeremo una clausola where che assomiglia al seguente
WHERE (e.sku like 'a%') AND (e.sku like 'b%')
Per quelli di voi che hanno appena alzato la mano, sì, l'esempio sopra restituirà sempre 0 record. Nessuno sku può iniziare con ENTRAMBE un a e un b. Ciò che probabilmente desideriamo qui è una query OR. Questo ci porta ad un altro aspetto confuso del secondo parametro di addFieldToFilter.
Se si desidera creare una query OR, è necessario passare una matrice di matrici di filtri come secondo parametro. Trovo che sia meglio assegnare le singole matrici di filtri alle variabili
public function testAction()
{
$filter_a = array('like'=>'a%');
$filter_b = array('like'=>'b%');
}
e quindi assegnare un array di tutte le mie variabili di filtro
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()
);
}
Nell'interesse di essere espliciti, ecco la suddetta matrice di matrici di filtri.
array($filter_a,$filter_b)
Questo ci darà una clausola WHERE che è simile alla seguente
WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
- Varien_Data_Collection :: addFilter
addFilter($field, $value, $type = 'and')
addFilter()
consente di filtrare un singolo campo solo per un singolo valore e un tipo. $type
può essere uno dei seguenti:
addFilter
conattributes
?