在我们开始介绍数据操作前,我们先介绍一个神兵利器—Varien Data Collections。在最早的时候我们写php通常用Array来做数据收集器,这个小东西可发挥了大作用,要知道如果你想在其他语言中实现Array有多么难过。
例如c、c++。

在php5中,更是发扬了Array,php内置了一些类和接口,允许你创建你自己的数据结构。Magento充分利用了这一点,在使用Varien_Data_Collection来做数据收集的时候,它实现了php内置IteratorAggregate对象迭代器和Countable两个接口。下面是用php内置类ArrayObject的一个例子。

$array=new ArrayObject();class MyCollection extends ArrayObject{}$collection=new MyCollection();$collection[]='bar';

在接下来的文章中,我认为你已经了解ArrayObject、IteratorAggregate、Countable。如果还是很陌生,我建议你先阅读这篇文章PHP5对象迭代(Object Iteration)。当然你不必了解很底层的东西,你只需要知道如何用就可以了。

适合对象:高级开发者

作者:精东

最后修改时间:2010年5月31日

版本:V 0.1.0

在Magento代码中,其实每个Model都有个Collection。了解这些数据收集器是如何工作的是你成为一个真正Magento开发人员的关键点。
下面让我们开始吧,前面我们创建过一个Helloworld模块,现在我们继续用他开始我们接下来的学习。

创建一个数据收集器

首先,我们创造一些新的对象。

$thing_1=new Varien_Object();$thing_1->setName('Richard');$thing_1->setAge(24);$thing_2=new Varien_Object();$thing_2->setName('Jane');$thing_2->setAge(12);$thing_3=new Varien_Object();$thing_3->setName('Spot');$thing_3->setLastName('The Dog');$thing_3->setAge(7);

Magento中所有的Model都继承Varien_Object,在面向对象编程中,这样做的好处是当你想往多个Model中添加方法的时候,你只需要简单地修改一个文件即可。

在继承Varien_Object的类中,有两个魔术方法,get/set,你可以很方便的向对象中加入一个属性(值),让我们看个例子。

var_dump($thing_1->getName());

如果你忘记了属性的名字,你可以将所有数据都获取到:

var_dump($thing_3->getData());

你将看到以下结果:

array'name'=> string 'Spot'(length=4)'last_name'=> string 'The Dog'(length=7)'age'=> int 7

注意last_name属性,是用下滑线分隔的,如果你想用get和set魔术方法,那么需要使用驼峰命名法。

$thing_1->setLastName('Smith');

在新版本的magento中你可以用array关联数组的方式获取数据。

var_dump($thing_3["last_name"]);

T这个归功于php5的新特性,ArrayAccess接口。也是 “Object Oriented Programming”.

现在然我们把这些对象加到数据收集器Varien_Data_Collection中。很多程序员将Collection看成是数组,当然我不反对。

$collection_of_things=new Varien_Data_Collection();$collection_of_things->addItem($thing_1)->addItem($thing_2)->addItem($thing_3);

大多数Magento data Collections继承于Varien_Data_Collection,你可以使用里面的任何一个方法。

那么我们可以做些什么呢?接下来我们使用foreach去循环它。

foreach($collection_of_thingsas$thing){var_dump($thing->getData());}

这里还有方法取出第一个数据和最后一个数据。

var_dump($collection_of_things->getFirstItem());var_dump($collection_of_things->getLastItem()->getData());

将你的数据转成xml

var_dump($collection_of_things->toXml());

只像取某一个字段

var_dump($collection_of_things->getColumnValues('name'));

Magneto还给我们提供了一些基本的过滤功能

var_dump($collection_of_things->getItemsByColumnValue('name','Spot'));

模型数据收集器(Model Collections)

前面我们有提到,所有Magento的模型数据收集器都继承Varien_Data_Collectionm,所以理论上我们可以使用之前的所有方法。下面让我们以product模型实战下。

publicfunction testAction(){$collection_of_products= Mage::getModel('catalog/product')->getCollection();var_dump($collection_of_products->getFirstItem()->getData());}

基本所有的Magento模型都有个方法叫getCollection默认情况下,它会返回系统中所有的数据。

Magento的数据收集器Collection包含很多复杂的逻辑来处理数据,无论是否使用索引或缓存、EAV表等。

上面的产品数据收集器,它里面还有Varien_Data_Collection_Db类。这个类给你很多有用的方法,例如如果你向看sql的select语句。

publicfunction testAction(){$collection_of_products= Mage::getModel('catalog/product')->getCollection();var_dump($collection_of_products->getSelect());//might cause a segmentation fault}

上面的方法将输出

object(Varien_Db_Select)[94]  protected '_bind'=>arrayempty  protected '_adapter'=>...

从上面可以看出,Magento使用的是ZendFramework的数据库链接层。接下来让我们看看更有意义的东西

publicfunction testAction(){$collection_of_products= Mage::getModel('catalog/product')->getCollection();//var_dump($collection_of_products->getSelect()); //might cause a segmentation faultvar_dump((string)$collection_of_products->getSelect());}

上面的方法将输出

'SELECT `e`.* FROM `catalog_product_entity` AS `e`'

有时也会比较复杂,例如

string 'SELECT `e`.*, `price_index`.`price`, `price_index`.`final_price`, IF(`price_index`.`tier_price`, LEAST(`price_index`.`min_price`, `price_index`.`tier_price`), `price_index`.`min_price`) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price` FROM `catalog_product_entity` AS `e`INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0'

这个差异取决于你选择的字段,同样也涉及到索引和缓存。如果你看过之前的文章,那么你应该知道很多Magento表是使用Eav表结构的,默认情况下一个eav的数据收集器将不会包含所有的对象字段,你可以通过addAttributeToSelect来添加它们。让我们看看例子。

$collection_of_products= Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*');//the asterisk is like a SQL SELECT *

或者你也可以只选某一个字段

//or just one$collection_of_products= Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('meta_title');

或者更多

//or just one$collection_of_products= Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('meta_title')->addAttributeToSelect('price');

延迟加载(Lazy Loading)

一般情况下,我们在创建sql后需要立刻执行,从而获取数据,例如。

$model=new Customer();//SQL Calls being made to Populate the Objectecho'Done';//execution continues

但是Magento不是这样的,它采用的是Lazy Loading。延迟加载意味着在程序需要数据前,sql是不执行的,如下。

$collection_of_products= Mage::getModel('catalog/product')->getCollection();

在这个时候Magento还没有链接数据库,你可以放心地去做你想要做的事。

$collection_of_products= Mage::getModel('catalog/product')->getCollection();$collection_of_products->addAttributeToSelect('meta_title');

你不必担心每次添加属性的时候Magento都会执行一个sql,去获取数据,sql只有在你需要数据的时候才会被执行。

Magento对数据库连接层做了良好的封装,当然它也考虑到了效率问题。在一般情况下,你没必要去担心sql后台是怎么执行的,只需要专心做你的功能,例如区块、布局等。这是Magento非常优秀的地方。

过滤数据(Filtering Database Collections)

最重要的一个方法是addFieldToFilter。通过这个方法可以添加我们sql中的WHERE语句。

publicfunction testAction(){$collection_of_products= Mage::getModel('catalog/product')->getCollection();$collection_of_products->addFieldToFilter('sku','n2610');//another neat thing about collections is you can pass them into the count      //function.  More PHP5 powered goodnessecho"Our collection now has ".count($collection_of_products).' item(s)';var_dump($collection_of_products->getFirstItem()->getData());}

addFieldToFilter方法中的第一个参数是你想过滤的字段名称,第二个是你想过滤的值。例如刚刚sku是字段名称,n2610是值。

第二个参数也可以被用来指定某一类型的数据。稍微有些复杂,我们继续往下看。

$collection_of_products->addFieldToFilter('sku','n2610');

这个等同于sql中的where条件句

WHERE sku ="n2610"

下面的例子自己尝试下

publicfunction 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')'

但是这个很快会变得很复杂。试着做下面的练习。

var_dump((string) Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*')->addFieldToFilter('meta_title','my title')->getSelect());

输出的将是下面的sql语句。

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`INNERJOIN`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=0LEFTJOIN`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语句,我们先不转移焦点,继续我们下面的讲解。

其它比较运算符

我确定在刚刚的练习中,你想知道如何实现一个不是“=”的where条件句,例如不等于、大于、小于。刚刚我们有讲过addFieldToFilter的第二个参数允许传入不同“类型”。
其实很简单,只要将一个简单的数组作为第二个参数传入addFieldToFilter方法就可以变换条件句。

数组的键就是“类型”,关联的值就是你想过滤的值。我们改写下上面的代码。

publicfunction testAction(){var_dump((string)     Mage::getModel('catalog/product')->getCollection()->addFieldToFilter('sku',array('eq'=>'n2610'))->getSelect());}

看上面的过滤器

addFieldToFilter('sku',array('eq'=>'n2610'))

正如你看到的,第二个参数是一个php的数组。它的键是“eq”,代表等于的意思。

Magento在这个函数中有一系列英语的缩写,这些词的资料可以参考《tear of remembrance》。这些沿用了Perl语言中的一些比较运算符号。

在这里我将Magento所有的条件判断符号列出来供大家参考。

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 equalWHERE (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

inandnin条件句中,语序你传入一个数组作为值。例如:

array("in"=>array('n2610','ABC123')WHERE (e.sku in ('n2610','ABC123'))

notnull, null

关键字NULL是最特殊的sql句,它将忽略你传入的值。

array("notnull"=>'n2610')WHERE (e.sku is NOT NULL)

from – to 过滤

这是另一种过滤方式,在传入的数组中,允许你传入两个键,是从哪里到哪里的意思,一个数值区间。

publicfunction 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

根据刚才讲的内容,你可以知道,通过多个addFieldToFilter方法可以获得一个”AND”的条件句。

function testAction(){echo((string)         Mage::getModel('catalog/product')->getCollection()->addFieldToFilter('sku',array('like'=>'a%'))->addFieldToFilter('sku',array('like'=>'b%'))->getSelect());}

等同于下面的子句

WHERE(e.sku LIKE'a%')AND(e.sku LIKE'b%')

但是,聪明的你可以发现,上面的例子不可能返回任何结果,因为一个sku不可能以a开头,同时也以b开头。
我们希望用的应该是”OR”,那么如何实现呢?这又使我们将焦点集中到了addFieldToFilter方法的第二个参数上。

如果你希望构造一个or的语句,首先我们构造两个参数。

publicfunction testAction(){$filter_a=array('like'=>'a%');$filter_b=array('like'=>'b%');}

然后将它们作为一组参数传入addFieldToFilter方法中,如下。

publicfunction 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());}

你可以看到这样的一个子句。

WHERE(((e.sku LIKE'a%')OR(e.sku LIKE'b%')))

总结

恭喜你,你现在已经是一个很不错的Magento开发者了!因为你不需要写任何sql语句,就可以获取几乎所有模型的所有你想要的数据。

转载于:https://blog.51cto.com/vick1992/1280997

深入理解Magento-第十章-数据操作数据收集器相关推荐

  1. 深入理解MAGENTO – 第九章 – 数据集合瓦瑞恩

    本来,作为一个PHP程序员,如果你想攒一组变量的相关你有一个选择,古老的 阵列 . 尽管共享一个地址的名称与C存储器的阵列,一个PHP数组是一种通用的字典可变数组索引像数值对象结合行为的影响. 在其他 ...

  2. java的垃圾回收机制包括:主流回收算法和收集器(jvm的一个主要优化方向)

    2019独角兽企业重金招聘Python工程师标准>>> java的垃圾回收机制是java语言的一大特色,解放了开发人员对内存的复杂控制,但如果你想要一个高级java开发人员,还是需要 ...

  3. 深入理解Magento – 第七章 – 自定义Magento系统配置

    深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第七章 – 自定义Magento系统配置 Magento拥有十分强大的后台管理系统.作为一名开发人员,这套后台管理 ...

  4. 深入理解Magento – 第六章 – 高级Magento模型

    深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第六章 – 高级Magento模型 我们讲过Magento有两种模型,简单模型和EAV(Entity Attrib ...

  5. 深入理解Magento – 第五章 – Magento资源配置

    深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第五章 – Magento资源配置 对于任何一个更新频繁的项目来说,保持开发环境和生产环境的数据库同步是件很头疼的 ...

  6. 深入理解Magento – 第四章 – 模型和ORM基础

    深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第四章 – 模型和ORM基础 对于任何一个MVC架构,模型(Model)层的实现都是占据了很大一部分.对于Mage ...

  7. 深入理解Magento – 第三章 – 布局,块和模板

    深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第三章 – 布局,块和模板 我们接着研究Magento.根据我们第二章讲的Magento MVC的架构,我们接下来 ...

  8. 深入理解Magento – 第二章 – Magento请求分发与控制器

    深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第二章 – Magento请求分发与控制器 Model-View-Controller (MVC) ,模型-视图- ...

  9. 怎么理解什么是大数据呢?

    如果你说大数据就是数据大,或者侃侃而谈4个V,也许很有深度的谈到BI或预测的价值,又或者拿Google和Amazon举例,技术流可能会聊起hadoop和Cloud Computing,不管对错,只是无 ...

最新文章

  1. java map深拷贝_java 实现Map的深复制
  2. Windows Server 2012 R2 WSUS-13:部署二级WSUS
  3. Redis: Redis Desk Manager Setup
  4. ASP 三十条精华代码
  5. node.js 爬虫中文乱码 处理
  6. python 学习笔记(3)-转载
  7. 设置 JAVA_HOME
  8. python正则表达式修饰符_python正则表达式,看完这篇文章就够了...
  9. 2021金蝶全球创见者大会成功举办, 500强企业共话EBC数字战斗力
  10. python有几种容器_Python中几种内置的容器(Containers)类型:列表、字典、集合和元组的比较和该注意的点...
  11. g++ vscode 环境选择_VSCode C++环境配置(个人使用)
  12. TabHost和ActivityGroup用法
  13. (转)详解HTML网页源码的charset格式
  14. 线性与非线性规划问题求解
  15. Linux C/C++UDP通信实现
  16. uniapp uView 微信小程序弹框二维码canvas不显示,以及显示后跟随滑动的问题
  17. fullpage框架
  18. 【洛谷】P2689 东南西北(dfs|贪心)
  19. luffy-16/订单表设计,立即付款接口/前端,支付成功get回调用户展示,支付成功post回调修改订单状态
  20. percona xtrabackup 之一 setup

热门文章

  1. happiness[国家集训队2011(吴确)]
  2. linux下vtune使用
  3. memcache的学习路线图
  4. Win7下JDK环境变量的设置
  5. ubuntukylin14安装ns-allinone-2.35教程(虚拟机ubuntu同理)
  6. windows2003——IIS
  7. MybatisPlus 通用枚举无法正确取值
  8. Web应用性能分析工具—HAR文件
  9. NUMPY数据集练习 ----------SKLEARN类
  10. iptables (2) 基本配置