`
天梯梦
  • 浏览: 13763581 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

深入理解Magento-第十章-数据操作&数据收集器

 
阅读更多

在我们开始介绍数据操作前,我们先介绍一个神兵利器—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) 。当然你不必了解很底层的东西,你只需要知道如何用就可以了。

 

在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_things as $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模型实战下。

public function 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语句。

public function 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' =>
    array
      empty
  protected '_adapter' =>
...

 

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

public function testAction()
{
    $collection_of_products = Mage::getModel('catalog/product')->getCollection();
    //var_dump($collection_of_products->getSelect()); //might cause a segmentation fault
    var_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 Object
echo '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语句。

public function 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 goodness
    echo "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"

 

下面的例子自己尝试下

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

 

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

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

 

其它比较运算符

 

我确定在刚刚的练习中,你想知道如何实现一个不是“=”的where条件句,例如不等于、大于、小于。刚刚我们有讲过addFieldToFilter的第二个参数允许传入不同“类型”。

其实很简单,只要将一个简单的数组作为第二个参数传入addFieldToFilter方法就可以变换条件句。数组的键就是“类型”,关联的值就是你想过滤的值。我们改写下上面的代码。

public function 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 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 and nin 条件句中,语序你传入一个数组作为值。例如:

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 过滤

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

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

根据刚才讲的内容,你可以知道,通过多个 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的语句,首先我们构造两个参数。

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

 

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

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

 

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

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

 

总结

 

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

 

 

原文链接:http://www.wemvc.com/1229.html

分享到:
评论

相关推荐

    Magento-中文开发教程

    深入理解Magento-第十章 – 数据操作&数据收集器 在Magento教程中用到的模块 Configviewer Layoutviewer Helloworld with Custom System Config 其他与Magento开发相关的文章 简单的EAV数据查询 清除缓存的几...

    深入理解Magento-2.pdf

    本文档提供了创建和 Magento的应用程序进行安装定制的店面主题的说明。它描述 Magento的内容呈现过 程,并说明该系统的对有效地建立一个主题要求的范围内的观点层。该文件还走过日常前端开发人员的任务。

    Magento深入理解Magento

    ### Magento深入理解——强大配置系统解析 #### 一、引言 Magento是一款极其灵活且功能丰富的电子商务平台,其核心竞争力之一在于其强大的配置系统。这一系统不仅为开发者提供了极高的定制化能力,还确保了平台的...

    magento-演示数据1.6.1.0

    Magento是一款强大的开源...总的来说,"magento-演示数据1.6.1.0"是一个宝贵的资源,它能加速Magento的学习过程,使用户能够更深入地了解这个平台的潜力,提高开发效率,并为客户提供更加真实和丰富的在线购物体验。

    magento-ce-2.4.0_sample_data-2020-07-26-02-51-57.tar.gz

    magento-ce-2.4.0_sample_data-2020-07-26-02-51-57.tar.gz Include sample data

    深入理解Magento.pdf

    【深入理解Magento——配置系统详解】 Magento是一款强大的开源电子商务平台,其配置系统是其核心组成部分,被誉为Magento的心脏。这个系统以XML的形式动态生成配置,掌控着模块、模型、类、模板等所有组件的行为。...

    Magento-中文开发教程.doc

    Magento是一款强大的开源电子商务平台,专为在线商家设计,提供丰富的功能和高度的可定制性。...通过学习这个教程,无论是初学者还是经验丰富的开发者,都能更深入地理解和运用Magento,打造功能强大的电子商务平台。

    深入理解magento

    总结,深入理解Magento意味着要掌握其请求处理机制、页面布局设计、数据模型以及高级编程模式。这不仅需要对PHP有扎实的基础,还需要熟悉Magento的架构和设计模式。通过学习和实践,开发者能够创建出高效、可维护的...

    magento-ce-2.4.0-2020-07-24-11-15-38.tar.gz

    magento-ce-2.4.0-2020-07-24-11-15-38.tar.gz 不带sample data

    magento-java-master.zip_magento

    8. **性能优化**:当处理大量数据或频繁调用API时,考虑缓存策略、批量操作和错误重试机制来提高性能和可靠性。 9. **安全实践**:遵循最佳安全实践,例如加密敏感信息,避免在代码中硬编码API密钥,定期轮换Access...

    Magento-Redismanager, 在 Magento,用于Redis的超级用户控制.zip

    Magento-Redismanager, 在 Magento,用于Redis的超级用户控制 Redis 管理Redis服务的实用程序特性系统&gt; 配置&gt;的自动或者手动配置高级&gt; Redis管理在负载均衡环境中缓存服务不同的理想情况直接从magento面板管理员管理...

    Magento-SMTP-Email

    本主题将深入探讨Magento的SMTP插件及其应用。 Magento的SMTP插件是为了克服默认邮件发送机制可能遇到的问题,如邮件被标记为垃圾邮件或无法送达。通过集成SMTP插件,商家可以使用自己的SMTP服务器,如Gmail、Yahoo...

    magento-1.9.1.1-2015-04-30-12-49-08

    这对于开发者来说是非常有价值的,因为他们可以根据业务需求自由定制功能,同时也可以深入理解Magento的工作原理。 在标签中,"magento"明确指出这是与Magento相关的项目。Magento作为一个强大的电子商务解决方案,...

    magento -redis 插件安装包

    Magento是一款强大的开源电子商务平台,而Redis则是一种高性能的键值数据存储系统,常用于缓存、session管理等场景。在Magento中集成Redis插件可以显著提升网站性能,降低数据库负载,尤其是在处理高并发请求时。...

    magento-1.8.0.0.tar.gz

    4. **报告与分析**:加强了数据分析功能,商家可以获取详细的销售、流量和客户行为报告,以优化经营策略。 5. **多语言与多货币支持**:支持多种语言和货币,便于全球销售。 三、开发与定制 1. **模板引擎**:...

    magento-ce-2.4.2-p1-2021-04-22-10-49-09.zip

    因为国外网速太慢了,所以下载后分享给需要的人。magento-ce-2.4.2-p1-2021-04-22-10-49-09

    magento-1.7.0.7z

    在深入探讨Magento 1.7.0的知识点之前,我们首先要了解它为何重要。Magento以其高度可定制性、丰富的功能集和广泛的社区支持闻名。1.7.0版本是 Magento 1.x 系列中的一个重要里程碑,引入了许多新特性、优化和安全...

    Magento-中文开发教程(技术重点2)

    数据收集器是 Magento 中的一种特殊模型,用于收集和处理数据。它们常用于报表生成、数据分析等场景。 #### 总结 通过本教程的学习,您已经了解了 Magento 的一些核心技术点,包括配置系统、请求分发与控制器、...

    magento-1.7.0.2汉化包|magento-1.7.0.2中文语言包下载

    描述中提到"汉化率达到98%以上",这意味着大部分的用户界面、帮助文档、错误消息以及系统提示都已经从英文翻译成了中文,使得不懂英文的用户也能顺畅地操作Magento后台。这对于国内商家来说是一个巨大的优势,因为它...

    Magento-CE-2.3.4_sample_data-2020-01-22-11-11-58.tar.gz

    Magento-CE-2.3.4_sample_data-2020-01-22-11-11-58.tar.gz源自官网

Global site tag (gtag.js) - Google Analytics