跨境电商
经验交流分享

Magento开发文档(八):Varien数据收集

magento

Magento中文手册(八):Varien数据收集

最早的时候,作为PHP程序员,如果你想获取一组相关的变量,最好的办法就是使用数组存储。在其它编程语言里,这个办法就显得不那么简单了。他们拥有多种数据结构可以选择,每个都在存储,速度和语法上有些区别。PHP这门语言则将这些选择统统抹掉,并且只给程序员最有用的数据结构来完成这项任务。

不过PHP5已经通过内置的类和接口,视图改变这种情况,允许程序员创建自己的数据结构。

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

之后这段对于译者来说有点难度,为了不误导大家,直接上英文。

While this is still galling to a certain type of software developer, as you don’t have access to low level implementation details, you do have the ability to create array-like Objects with methods that encapsulate specific functionality. You can also setup rules to offer a level of type safety by only allowing certain kinds of Objects into your Collection.

It should come as no surprise that Magento offers you a number of these Collections. In fact, every Model object that follows the Magento interfaces gets a Collection type for free. Understanding how these Collections work is a key part to being an effective Magento programmer. We’re going to take a look at Magento Collections, starting from the bottom and working our way up. Setup a controller action where you can run arbitrary code, and let’s get started.

数据收集

首先,我们实例化Varien_Object()类,创建一些新的对象。

[php]
$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);
[/php]

所有的Magento模型都继承自Varien_Object()类。这在面向对象架构中是一个常用的设计模式,你可以轻易的添加新的方法或功能到任意一个对象,而不用修改类文件。

任何继承自Varien_Object()类的对象都拥有getter和setter魔术方法,可以方便的用来设置属性值。试下下面这段代码,

[php]
var_dump($thing_1->getName());
[/php]

如果你还不晓得该获取什么属性,例如上面的getName()中的Name,也可以直接读取所有的数据到一个数组中,

[php]
var_dump($thing_3->;getData());
[/php]

上面这段代码会返回类似下面的一个数组,

[php]
array
‘name’ => string ‘Spot’ (length=4)
‘last_name’ => string ‘The Dog’ (length=7)
‘age’ => int 7
[/php]

注意下名为“last_name”的属性,如果属性名中包含有下划线,你必须以驼峰命名的方式才能使用getter和setter魔术方法调用它。

[php]
$thing_1->setLastName(‘Smith’);
[/php]

在Magento的最新版本中,你也可以使用数组的形式来读取该属性。

[php]
var_dump($thing_3["last_name"]);
[/php]

获取一些对象之后,我们给他们添加收集(Collection)。收集像数组一样,但它由PHP程序员定义。

[php]
$collection_of_things = new Varien_Data_Collection();
$collection_of_things
->addItem($thing_1)
->addItem($thing_2)
->addItem($thing_3);
[/php]

绝大部分Magento数据收集继承自Varien_Data_Collection()类。任何集成自该类的方法都能够使用它的方法。(我觉得这句是废话)。

数据收集可以做些什么呢?首先,我们可以使用foreach语句循环数据

[php]
foreach($collection_of_things as $thing) {
var_dump($thing->getData());
}
[/php]

还有两个方法,分别可以获取第一个和最后一个数据,

[php]
var_dump($collection_of_things->getFirstItem());
var_dump($collection_of_things->getLastItem()->getData());
[/php]

当然还可以输出为XML格式~~

[php]
var_dump( $collection_of_things->toXml() );
[/php]

只获取单独的一个字段,

[php]
var_dump($collection_of_things->getColumnValues(‘name’));
[/php]

Magento团队同样提供了一些基础的过滤方法,

[php]
var_dump($collection_of_things->getItemsByColumnValue(‘name’,’Spot’));

[/php]

模型收集

这些可能很有意思,但是为什么我们需要关注它呢?这是因为Magento内置的数据收集都继承自该类。也就是说,对于产品收集(或者分类收集),你可以使用同样的方法。看下下例,

[php]
public function testAction() {
$collection_of_products = Mage::getModel(‘catalog/product’)->getCollection();
var_dump($collection_of_products->getFirstItem()->getData());
}
[/php]

Magento模型对象多数拥有getCollection()方法,默认的,它返回系统中和该对象同类型的对象的收集。Most Magento Model objects have a method named getCollection which will return a collection that, by default, is initialized to return every Object of that type in the system.

产品收集,以及Magento中其他的收集,还同样继承自Varien_Data_Collection_Db类。该类同样提供了很多有用的方法。例如,如果你想查看某个收集使用的select查询语句,

[php]
public function testAction() {
$collection_of_products = Mage::getModel(‘catalog/product’)->getCollection();
var_dump($collection_of_products->getSelect());
}
[/php]

上面一段代码会输入如下内容,

object(Varien_Db_Select)[94]
protected ‘_bind’ =>
array
empty
protected ‘_adapter’ =>

因为Magento使用的是Zend的数据库抽象层,Select查询语句是个对象。让我们将其转换为字符串,

[php]
public function testAction() {
$collection_of_products = Mage::getModel(‘catalog/product’)->getCollection();
var_dump((string)$collection_of_products->getSelect());
}
[/php]

这段代码可能会返回一个简单的select语句,

‘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()方法添加选取的属性。

[php]
$collection_of_products = Mage::getModel(‘catalog/product’)
->getCollection()
->addAttributeToSelect(‘*’);
[/php]

或者,可以只添加一个属性,

[php]
$collection_of_products = Mage::getModel(‘catalog/product’)
->getCollection()
->addAttributeToSelect(‘meta_title’);
[/php]

还可以直接以链接的方式选择多个属性

[php]
$collection_of_products = Mage::getModel(‘catalog/product’)
->getCollection()
->addAttributeToSelect(‘meta_title’)
->addAttributeToSelect(‘price’);
[/php]

数据库延迟加载

刚接触Magento ORM系统的程序员对于Magento数据库的调用问题会非常头疼。当使用纯SQL语句或者普通的ORM系统时,SQL语句会在对象实例化之后立刻被调用。

[php]
$model = new Customer();
//sql语句调用
echo ‘Done’; //执行结束
[/php]

Magento的运行方式于此不同,延迟加载的概念被应用于Magento数据库调用中。简单来说,延迟加载是SQL不会被立刻执行,知道客户端程序员需要调用该数据时。例如,当编写如下代码时,

[php]
$collection_of_products = Mage::getModel(‘catalog/product’)->getCollection();
[/php]

Magento实际上并未运行任何的数据库操作,你仍然可以继续添加需要select的属性,

[php]
$collection_of_products = Mage::getModel(‘catalog/product’)-getCollection();
//其他操作
$collection_of_products->addAttributeToSelect(‘meta_title’);
[/php]

并且,Magento同样不会在添加一个新的属性之后运行任何数据库查询。即在你试图在收集中尝试读取内容之前,数据库不会进行任何查询。

过滤数据库收集

在数据库收集中最重要的方法就应该是addFieldToFilter()了。该方法将where字句添加到查询语句当中,一起看下下面的这段代码(将参数二替换为你产品中的sku)

[php]
public function testAction() {
$collection_of_products = Mage::getModel(‘catalog/product’)->getCollection();
$collection_of_products->addFieldToFilter(‘sku’, ‘你的产品sku’);

//除此之外,还可以将收集传递个count()函数,计算select的数目
echo "该收集包含" . count($collection_of_products) . ‘个记录’;
var_dump($collection_of_products->getFirstItem()->getData());
[/php]

addFieldToFilter()方法的参数一是你希望过滤的属性,参数二是该属性的值。对于参数二,还可以指定为过滤的类型。下面看下使用该方法进行的稍微复杂的过滤。

上面说过,下面这段代码,相当于数据库中的where字句“WHERE sku = ‘xxx’”

[php]
$collection_of_products->addFieldToFilter(‘sku’, ‘xxx’);
[/php]

不相信?哈哈,下面这段代码可以直接输出该收集的查询语句,

[php]
public function testAction() {
var_dump( (string)
Mage::getModel(‘catalog/product’)->getCollection()
->addFieldToFilter(‘sku’, ‘xxx’)->getSelect()
);
}
[/php]

输出如下,

SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = ‘xxx’)

必须谨记于心的是,这在使用EAV属性的时候,这些很快就会变的非常复杂,例如选择所有属性,

[php]
var_dump( (string)
Mage::getModel(‘catalog/product’)->getCollection()
->addAttributeToSelect(‘*’)->addFieldToFilter(‘sku’, ‘xxx’)
->getSelect()
)
[/php]

输出的将会是如下比较庞大的查询语句,

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

addFieldToFilter()方法提供的更多查询子句

2011年10月14日23:27:26 睡觉

赞(0)
未经允许不得转载:锐想 » Magento开发文档(八):Varien数据收集
分享到: 更多 (0)

评论 5

评论前必须登录!

 

  1. #1

    collection翻译为集合更好些

    bluex5年前 (2014-04-22)
    • 对的,应该翻译成集合,当时刚接触的时候对这个概念理解的不是太好,谢谢指教。

      ruiwant5年前 (2014-07-07)
  2. #2

    “你可以轻易的添加新的方法或功能到任意一个对象,而不用修改类文件。”这句翻译有问题啊,应该是“你可以轻易的添加方法到系统中每个对象,而不需要修改每个类文件(即:修改一个总父类Varien_Object,给它添加一个方法,随即系统中所有对象都将拥有该方法。)”

    感冒了,啊逑!5年前 (2014-07-20)
    • 当时刚刚接触这些内容,很多翻译不是很到位。谢谢指教!

      ruiwant5年前 (2014-07-23)

锐想电商 - 跨境电商经验交流分享

锐想无限