Respostas:
OK, vamos examiná-los. A primeira diferença é que addFilter()
é mais genérico e não específico do banco de dados. Também é usado Varien_Directory_Collection
para filtrar por nome de arquivo. Mas para esta resposta eu vou focar Varien_Data_Collection_Db
.
Eles têm uma assinatura diferente, onde addFilter
parece ser menos flexível, mas você verá que também tem suas vantagens:
/**
* 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 () pode usar uma matriz de campos com uma matriz de condições ou um único campo com uma única condição:
addFieldToFilter('field', 'value')
Resulta em: field=value
addFieldToFilter(['field1', 'field2'], ['value1', 'value2']);
Resulta em: field1=value1 OR field2=value2
Cada condição pode ser:
'value1'
e 'value2'
acima)[ operator => value ]
Zend_Db_Expr
objetoIsso, especialmente a sintaxe "operator => value", está documentada no código em Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition()
- lembre-se disso, eu as busco com frequência:
* 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
Há um recurso não documentado adicional no operador from
/ to
:
['from' => $dateFrom, 'to' => $dateTo, 'date' => true]
os valores $dateFrom
e $dateTo
serão analisados como datas. Eles podem ter qualquer forma que seja aceita porVarien_Date::formatDate()
<=
ou >=
, poderá omitir um 'from'
ou 'to'
.'datetime' => true
também deve funcionar e incluir a hora, não apenas o dia, mas há um erro no Varien_Db_Adapter_Pdo_Mysql :: _ prepareSqlDateCondition () ( $includeTimestamp
parâmetro ausente ) que faz o datetime
trabalho da mesma maneira que date
. Ambos incluem o tempo. Portanto, se você precisar comparar apenas por data, adicione 00:00:00
à from
data e 23:59:59
à to
data.O método usa mapeamento de campo. Os mapeamentos de campo podem ser definidos em classes de coleta concretas para criar nomes de campos alternativos. Aqui está um exemplo da coleção de produtos:
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()
permite apenas filtrar um único campo por um único valor e um tipo . $type
pode ser qualquer um de:
AND $field=$value
à cláusula WHERE (é claro, com citações apropriadas)"OR $field=$value
à cláusula WHERE (idem)AND $value
à cláusula WHERE (ou seja, $ value pode ser uma expressão SQL arbitrária)_getConditionSql()
, semelhante a addFieldToFilter()
. Isso o torna quase tão poderoso quanto, apenas falta o recurso de adicionar vários filtros para campos diferentes combinados com OU.Em Varien_Data_Collection_Db::_renderFilters()
você pode ver como eles são processados.
Há uma diferença importante que é uma vantagem addFilter()
. Ele coleta os filtros a serem aplicados $this->_filters()
e os adiciona apenas ao Zend_Db_Select
objeto de consulta antes de carregar a coleção. addFieldToFilter()
por outro lado, manipula o objeto de consulta imediatamente.
Isso permite manipular ou remover filtros que já foram adicionados. A coleção Varien não possui uma interface, você deve implementá-la em sua coleção personalizada. Existe um método de gancho _renderFiltersBefore()
que você pode substituir.
A coleção Magento tem dois métodos para filtrar abaixo diferentes
- Varien_Data_Collection_Db :: addFieldToFilter
addFieldToFilter ($ field, $ condition = null)
O primeiro parâmetro de addFieldToFilter
é o atributo pelo qual você deseja filtrar. O segundo é o valor que você está procurando. Aqui estamos adicionando um sku
filtro para o valor n2610
.
O segundo parâmetro também pode ser usado para especificar o tipo de filtragem que você deseja fazer. É aqui que as coisas ficam um pouco complicadas e vale a pena aprofundar um pouco mais.
Então, por padrão, o seguinte
$collection_of_products->addFieldToFilter('sku','n2610');
é (essencialmente) equivalente a
WHERE sku = "n2610"
Dê uma olhada por si mesmo. Executando o seguinte
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku','n2610')
->getSelect());
}
vai render
SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'
Lembre-se de que isso pode ficar complicado rapidamente se você estiver usando um atributo EAV. Adicionar um atributo
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('meta_title','my title')
->getSelect()
);
e a consulta fica complicada.
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')
Para não insistir no assunto, tente não pensar muito no SQL se estiver dentro do prazo.
Outros operadores de comparação Tenho certeza de que você está se perguntando "e se eu quiser algo diferente de igual por consulta"? Diferente, maior que, menor que etc. O segundo parâmetro do método addFieldToFilter também o abordou. Ele suporta uma sintaxe alternativa, onde, em vez de passar uma string, você passa um único elemento Array.
A chave dessa matriz é o tipo de comparação que você deseja fazer. O valor associado a essa chave é o valor pelo qual você deseja filtrar. Vamos refazer o filtro acima, mas com esta sintaxe explícita
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('eq'=>'n2610'))
->getSelect()
);
}
Chamando nosso filtro
addFieldToFilter('sku',array('eq'=>'n2610'))
Como você pode ver, o segundo parâmetro é uma matriz PHP. Sua chave é eq, que significa igual. O valor dessa chave é n2610, que é o valor que estamos filtrando.
O Magento possui vários filtros semelhantes ao idioma inglês que trarão uma lágrima de lembrança (e talvez dor) a qualquer desenvolvedor de perl antigo na platéia.
Listados abaixo estão todos os filtros, juntamente com um exemplo de seus equivalentes 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'
A maioria delas é auto-explicativa, mas algumas merecem destaque especial
in, nin, find_in_set Os condicionais in e nin permitem passar uma matriz de valores. Ou seja, é permitido que a parte do valor da sua matriz de filtros seja uma matriz.
array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))
notnull, null A palavra-chave NULL é especial na maioria dos tipos de SQL. Normalmente, não funciona bem com o operador de igualdade padrão (=). A especificação de nulo ou nulo como seu tipo de filtro fornecerá a sintaxe correta para uma comparação NULL, ignorando o valor que você passar
array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)
de - para filtrar Esse é outro formato especial que quebra a regra padrão. Em vez de uma matriz de elemento único, você especifica uma matriz de dois elementos. Um elemento tem a chave de, o outro elemento tem a chave de. Conforme as teclas indicadas, esse filtro permite criar um intervalo de / para sem ter que se preocupar com símbolos maiores e menores que
public function testAction
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('price',array('from'=>'10','to'=>'20'))
->getSelect()
);
}
Os rendimentos acima
WHERE (_table_price.value >= '10' and _table_price.value <= '20')'
AND ou OR, ou são OR e AND? Finalmente, chegamos aos operadores booleanos. É o raro momento em que estamos filtrando apenas um atributo. Felizmente, as coleções do Magento nos cobrem. Você pode encadear várias chamadas para addFieldToFilter para obter um número de consultas "AND".
function testAction()
{
echo(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('like'=>'a%'))
->addFieldToFilter('sku',array('like'=>'b%'))
->getSelect()
);
}
Ao encadear várias chamadas como acima, produziremos uma cláusula where que se parece com a seguinte
WHERE (e.sku like 'a%') AND (e.sku like 'b%')
Para aqueles que levantaram sua mão, sim, o exemplo acima sempre retornaria 0 registros. Nenhum sku pode começar com AMB e a e b. O que provavelmente queremos aqui é uma consulta OR. Isso nos leva a outro aspecto confuso do segundo parâmetro do addFieldToFilter.
Se você deseja criar uma consulta OR, precisa passar uma Matriz de filtro Matrizes como o segundo parâmetro. Acho melhor atribuir seu filtro individual Arrays a variáveis
public function testAction()
{
$filter_a = array('like'=>'a%');
$filter_b = array('like'=>'b%');
}
e depois atribuir uma matriz de todas as minhas variáveis de 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()
);
}
No interesse de ser explícito, aqui está a matriz acima mencionada de matrizes de filtro.
array($filter_a,$filter_b)
Isso nos dará uma cláusula WHERE que se parece com a seguinte
WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
- Varien_Data_Collection :: addFilter
addFilter($field, $value, $type = 'and')
addFilter()
permite apenas filtrar um único campo por um único valor e um tipo. $type
pode ser qualquer um de:
addFilter
comattributes
?