Answers:
好,让我们检查一下。第一个区别是addFilter()
更通用,而不是特定于数据库。还可用于Varien_Directory_Collection
按文件名过滤。但是对于这个答案,我将重点关注Varien_Data_Collection_Db
。
它们的方法具有不同的签名,addFilter
似乎不太灵活,但是您会发现它也具有优点:
/**
* 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
对象这尤其是“ operator => value”语法记录在以下代码中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
应该也可以工作,并包括时间,不仅是日期,而且Varien_Db_Adapter_Pdo_Mysql :: __ prepareSqlDateCondition()(缺少$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',
));
/**
* 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子句(同上)AND $value
到WHERE子句(即$ value可以是任意SQL表达式)_getConditionSql()
,类似于addFieldToFilter()
。这使其功能几乎一样强大,只是缺少为OR组合的不同字段添加多个过滤器的功能。在 Varien_Data_Collection_Db::_renderFilters()
您可以看到它们的处理方式。
有一个重要的区别是对...有好处addFilter()
。它收集要应用的过滤器,$this->_filters()
并且仅Zend_Db_Select
在加载集合之前将它们添加到查询对象中。addFieldToFilter()
另一方面,立即操作查询对象。
这使您可以操作或删除已添加的过滤器。Varien集合没有为此提供接口,您必须在自定义集合中实现此接口。有一个挂钩方法_renderFiltersBefore()
可以覆盖。
Magento集合有两种过滤波纹管的方法
- Varien_Data_Collection_Db :: addFieldToFilter
addFieldToFilter($ field,$ condition = null)
的第一个参数addFieldToFilter
是您希望作为过滤依据的属性。第二个是您要寻找的价值。这是我们sku
为value 添加一个过滤器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')'
请记住,如果您使用的是EAV属性,这可能会很快变得复杂。添加属性
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方法的第二个参数也已在此处介绍。它支持一种替代语法,在该语法中,您无需传递字符串,而是传递单个元素Array。
该数组的关键是要进行比较的类型。与该键关联的值是您要作为过滤依据的值。让我们重做上面的过滤器,但是使用这种显式的语法
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('eq'=>'n2610'))
->getSelect()
);
}
调出我们的过滤器
addFieldToFilter('sku',array('eq'=>'n2610'))
如您所见,第二个参数是PHP Array。它的键是eq,表示等于。该键的值为n2610,这是我们要过滤的值。
Magento有许多这样的英语语言,例如过滤器,它会给听众中的所有老Perl开发人员带来纪念(或痛苦)的眼泪。
下面列出了所有筛选器,以及它们的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'
其中大多数是不言自明的,但有一些值得特别说明
in,nin,find_in_set in和nin条件语句允许您传入值数组。也就是说,您的过滤器数组的值部分本身允许为数组。
array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))
notnull,null关键字NULL在大多数SQL版本中都是特殊的。它通常不能与标准的等号(=)运算符配合使用。指定notnull或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')'
AND或OR,还是OR和AND?最后,我们介绍布尔运算符。这是罕见的时刻,我们只按一个属性进行过滤。幸运的是,Magento的收藏涵盖了我们。您可以将对addFieldToFilter的多个调用链接在一起,以获取多个“ AND”查询。
function testAction()
{
echo(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('like'=>'a%'))
->addFieldToFilter('sku',array('like'=>'b%'))
->getSelect()
);
}
通过如上所述将多个调用链接在一起,我们将生成一个where子句,其外观类似于以下内容
WHERE (e.sku like 'a%') AND (e.sku like 'b%')
对于刚刚举手的人,是的,上面的示例将始终返回0条记录。sku不能以a a和b开头。我们可能想要的是一个OR查询。这将我们带到了addFieldToFilter的第二个参数的另一个令人困惑的方面。
如果要构建OR查询,则需要传入一个Array of filter数组作为第二个参数。我发现最好将各个过滤器数组分配给变量
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。
array($filter_a,$filter_b)
这将为我们提供WHERE子句,其外观类似于以下内容
WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
- Varien_Data_Collection :: addFilter
addFilter($field, $value, $type = 'and')
addFilter()
仅允许按单个值和类型过滤单个字段。$type
可以是以下任何一个:
addFilter
同attributes
?