从上一节的示例代码中,您可能会发现不仅仅实例化了Product模型,还调用了getCollection()方法,getCollection()方法是Mage_Core_Model_Abstract抽象类的一部分,也就是说Magento中的所有模型都可以调用这个方法。
注:所有的集合都继承Varien_Data_Collection
Magento的集合实际上就是一个包含其它模型的模型,所以我们可以用Product集合来取代数组存放一组产品。集合除了可以提供一个更为便捷的模型分组数据结构,还提示一些可用于操作实体集合的一些特定方法,其中较为有用的方法有:
- addAttributeToSelect:用于为集合中实体添加属性,可使用星号*来作为通配符来添加所有属性
- addFieldToFilter:用于为集合添加一个属性滤镜,该函数用于普通的非EAV模型
- addAttributeToFilter:方法用于过滤EAV实体中的集合
- addAttributeToSort:该方法用于添加属性来进行排序
- addStoreFilter:该方法用于存储可用性滤镜,包含可用产品
- addWebsiteFilter:该方法为集合添加一个站点滤镜
- addCategoryFilter:该方法用于为产品集合指定分类滤镜
- addUrlRewrite:该方法用于向产品添加URL重写数据
- setOrder:该方法用于设定集合的排序
这里仅列出了一部分集合方法,每个集合依据相应的实体类型采用不同的方法。例如,customer集合Mage_Customer_Model_Resource_Customer_Collection对应一个特定方法groupByEmail(),从名称就可以看出它是一个对内部实体email的分组。
参照前面的例子,我们还是会使用产品模型,就当前而言产品集合:
为了说明如何使用集合,我们将采用一些常用与产品相关的案例来进行讲解:
- 从某一类别中获取产品集合
- 获取从指定日期X开始的新产品
- 获取最畅销(bestseller)产品
- 通过可见性过滤产品集合
- 过滤出没有图片的产品
- <href=”#multiple”>添加多种排序
从特定类别中获取产品集合
很多程序员在刚开始接触Magento时就需要从某一特定分类中获取产品集合,很多人会使用addCategoryFilter()或addAttributeToFilter()方法来进行过滤。事实上,还有更简单的方法,只是不太容易想到。最简单的方法不是先获得产品然后添加一个分类来进行过滤,其实只需实例化需要用到的分类,然后获取产品集合即可,下面我们通过前面安装的IMC(Magento Interactive Console,见Magento ORM与数据集合一节)来运行如下代码:
$category = Mage::getModel('catalog/category')->load(5); $productCollection = $category->getProductCollection();
getProductCollection()方法在Mage_Catalog_Model_Category类中定义,该函数代码如下:
public function getProductCollection() { $collection = Mage::getResourceModel('catalog/product_collection') ->setStoreId($this->getStoreId()) ->addCategoryFilter($this); return $collection; }
可以看出,该函数仅仅是为产品集合实例化了一个资源模型,也就是说,将店铺设为当前的store ID,并将需查找的类别传入addCategoryFilter()方法。这主要用于优化Magento的性能,也简化了开发人员的工作,因为在大多数情况下都可以通过分类进行操作。
获取从指定日期X开始的新产品
上面我们学习了如何通过特定类别来获取产品集合,那么我们再来看看是否可以通过其它条件来进行过滤获取产品。本例中我们将尝试获取在2013年12月之后所添加的产品。通过在IMC中运行示例代码可以获取在指定日期后创建的产品集合:
// Product collection from our previous example $productCollection->addFieldToFilter('created_at', array('from' => '2013-12-01));
是不是非常的简单?我们甚至还可以添加一个条件来获取两个日期之间添加的产品,比如我们通过以下示例代码获取12月当月创建的产品:
$productCollection->addFieldToFilter('created_at', array('from' => '2013-12-01)); $productCollection->addFieldToFilter('created_at', array('to' => '2013-12-30));
Magento的addFieldToFilter方法支持如下条件表达式:
Attribute code | SQL condition |
---|---|
eq | = |
neq | != |
like | LIKE |
nlike | NOT LIKE |
in | IN () |
nin | NOT IN () |
is | IS |
notnull | NOT NULL |
null | NULL |
moreq | >= |
gt | > |
lt | < |
gteq | >= |
lteq | <= |
我们还可以使用其它类型的过滤,比如在上面的日期过滤代码后添加如下代码来获取可见产品:
$productCollection->addAttributeToFilter('visibility', 4);
这个可见性属性是由产品用来控制产品在何处显示的特殊属性,它可以有如下值:
- 单独不可见:值为1
- 目录中可见:值为2
- 搜索中可见:值为3
- 目录和搜索中可见:值为4
获取最畅销(bestseller)产品
要获取指定类别Bestseller产品,我们需要更进一步,连接一下sales_order这张表。后面可通过创建一个特别分类或自定义报表来轻易地获取bestseller产品,我们可以在IMC中运行如下代码:
$category = Mage::getModel('catalog/category')->load(5); $productCollection = $category->getProductCollection(); $productCollection->getSelect() ->join(array('o'=> 'sales_flat_order_item'), 'main_table. entity_id = o.product_id', array('o.row_total','o.product_id'))- >group(array('sku'));
我们来分析一下上面的第三行代码,getSelect()方法直接继承Varien_Data_Collection_Db,将返回一个包含存储select语句和提供了指定join和group方法集合的变量(无需使用SQL语句)。这并不是为一个集合添加join的唯一方法,事实上,更为清晰的方法是使用joinField()函数,下面就使用这个函数来重写前面的代码:
$category = Mage::getModel('catalog/category')->load(5); $productCollection = $category->getProductCollection(); $productCollection->joinField('o', 'sales_flat_order_item', array('o. row_total','o.product_id'), 'main_table.entity_id = o.product_id') ->group(array('sku'));
通过可见性过滤产品集合
这可以轻松地通过addAttributeToFilter方法实现,Magento中的产品有一个称为可见性(visibility)的系统属性,为1至4之间的值。这里我们以可见值为4的产品为例,也就是说产品在搜索和目录中均可见,可在IMC中运行如下代码:
$category = Mage::getModel('catalog/category')->load(5); $productCollection = $category->getProductCollection(); $productCollection->addAttributeToFilter('visibility', 4);
过滤出没有图片的产品
如果使用第三方的导入系统的话,过滤出无图片的产品非常容易,但有时可靠性存在问题。和前面所讨论的其它内容一样,产品图片也是产品的一个属性:
$category = Mage::getModel('catalog/category')->load(5); $productCollection = $category->getProductCollection(); $productCollection->addAttributeToFilter('small_image',array('notnull' =>'','neq'=>'no_selection'))
通过添加额外的过滤,我们要求产品指定了小图片,默认情况Magento有三种图片类型:thumbnail, small_image和image。这三种类型在应用程序的不同地方使用,如果想要的话还可以对产品添加更为严格的规则.
$productCollection->addAttributeToFilter('small_image', array('notnull'=>'','neq'=>'no_selection')); ->addAttributeToFilter('thumbnail, array('notnull'=>'','neq'=>'no_ selection')) ->addAttributeToFilter('image', array('notnull'=>'','neq'=>'no_ selection'));
只有包含以上三种类型的产品才会被包含在我们集合中,读者可尝试使用其它图片类型来进行过滤。
添加多种排序
最后,让我们对集合先通过库存从大到小排序再通过价格由高到底排序。要获取库存状态的信息,需要使用一个只在addStockStatusToSelect()状态资源模型中存在的方法,该模型负责为我们的集合查询生成相对应的SQL语句:
$category = Mage::getModel('catalog/category')->load(5); $productCollection = $category->getProductCollection(); $select = $productCollection->getSelect(); Mage::getResourceModel('cataloginventory/stock_status')->addStockStatu sToSelect($select, Mage::app()->getWebsite()); $select->order('salable desc'); $select->order('price asc');
在查询语句中,Magento会通过可卖状态(true或false)和价格来进行排序,最终结果所有有库存产品会按价格从高到低排序,然后out-of-stock的产品会按价格从高到低排序。读者可通过不同的排序组合来看看Magento如何组纪念品和排序产品集合的。
下一节我们一起来学习有关在Magento中如何使用SQL的相关知识。