第六章 – 高级Magento模型2

添加实体类型

首先我们修改安装脚本如下

$installer
 =
 $this
;
 
$installer -> addEntityType ( 'helloworld_eavblogpost' , Array (
//entity_mode is the URL you'd pass into a Mage::getModel() call
'entity_model' => 'helloworld-eav/eavblogpost' ,
//blank for now
'attribute_model' => '' ,
//table refers to the resource URI helloworld-eav/blogpost
//<helloworld -eav_mysql4>…<blogpost><table>eavblog_posts</table>
'table' => 'helloworld-eav/blogpost' ,
//blank for now, but can also be eav/entity_increment_numeric
'increment_model' => '' ,
//appears that this needs to be/can be above "1" if we're using eav/entity_increment_numeric
'increment_per_store' => '0'
) ) ;

我们调用了资源配置对象的“addEntityType”方法。这个方法的参数是实体类型(helloworld_eavblogpost)还有和 这个类 型相关的参数。当你运行这个脚本以后,你会发现“eav_attribute_group”,“eav_attributeset”还有 “eav_entity_type”数据表中有了新的数据。访问以下URL

http:
//127.0.0.1/Magento/helloworld/blog/eavRead/id/1

你应该看到以下异常

SQLSTATE[
42S02]
:
 Base table or view not found:
 1146
 Table 'eavblog_posts'
 doesn't exist
创建数据表

我们已经告诉Magento我们的实体类型。接下来,我们要创建用来存储数据的数据表,并配置系统让Magento知道我们要用这些表。

如果你研究过Magento核心模块的资源配置脚本的话,比如core/Mage/CatalogInventory的配置脚本,你会看到很多用来 创建数 据表的SQL语句。所幸的是,我们已经不必要这样做了。Magento提供的资源配置类有一个方法“createEntityTables”。我们可以用 这个方法来创建我们需要的数据表。同时这个方法也会在Magento的系统数据表中添加相应的配置数据。

$installer
->
createEntityTables
(
 
$this -> getTable ( 'helloworld-eav/blogpost' )
) ;

“createEntityTables”有两个参数。第一个参数是基础表名(base table name)。第二个参数是一系列选项。我们这里忽略了第二个参数,这些参数都是一些高级配置,超出了我们讨论的范围。在运行了上述脚本以后,你会发现数据 库中添加了如下数据表

eavblog_posts 
eavblog_posts_datetime
eavblog_posts_decimal
eavblog_posts_int
eavblog_posts_text
eavblog_posts_varchar

同时,你会发现在“eav_attribute_set”表中多了一条数据

mysql>
 select *
 from eav_attribute_set order by attribute_set_id DESC LIMIT 1
 /G 
*************************** 1. row ***************************
attribute_set_id: 63
entity_type_id: 31
attribute_set_name: Default
sort_order: 3

清空Magento缓存,重新访问如下URL

http:
//127.0.0.1/Magento/helloworld/blog/eavRead/id/1

你应该看到以下输出

Loading the blogpost with an ID of 1
 
array ( 0 ) { }
添加属性

创建资源配置的最后一步是告诉Magento我们的模型有哪些属性。这就和为单独的数据表添加列是一样的。【注:我们上面的输出是空的就是因为我们 虽然创建了EAV数据表,但是却没有创建EAV属性,就像创建了一张没有任何列的数据表,当然是空的。】和上面的步骤一样,Magento的资源配置类提 供了相应的帮助函数,“installEntities”和“getDefaultEntities”。

我们之前所做的是告诉Magento,我们创建了一个实体类型(Entity Type),而现在,我们要配置这个实体类型使它能够和我们的模型相符合。这个方法名字有点搞“installEntities”,其实我们要做的是配置 这个实体。修改类“Wemvc_Helloworld_Model_Setup_Entity_Setup”

class Wemvc_Helloworld_Model_Setup_Entity_Setup extends Mage_Eav_Model_Entity_Setup { 
<?php
class Wemvc_Helloworld_Model_Entity_Setup extends Mage_Eav_Model_Entity_Setup {
public function getDefaultEntities( )
{
return array (
'helloworld_eavblogpost' => array (
'entity_model' => 'helloworld-eav/eavblogpost' ,
'attribute_model' => '' ,
'table' => 'helloworld-eav/blogpost' ,
'attributes' => array (
'title' => array (
//the EAV attribute type, NOT a mysql varchar
'type' => 'varchar' ,
'backend' => '' ,
'frontend' => '' ,
'label' => 'Title' ,
'input' => 'text' ,
'class' => '' ,
'source' => '' ,
// store scope == 0
// global scope == 1
// website scope == 2
'global' => 0 ,
'visible' => true ,
'required' => true ,
'user_defined' => true ,
'default' => '' ,
'searchable' => false ,
'filterable' => false ,
'comparable' => false ,
'visible_on_front' => false ,
'unique' => false ,
) ,
'post' => array (
//the EAV attribute type, NOT a mysql varchar
'type' => 'text' ,
'backend' => '' ,
'frontend' => '' ,
'label' => 'Post' ,
'input' => 'text' ,
'class' => '' ,
'source' => '' ,
// store scope == 0
// global scope == 1
// website scope == 2
'global' => 0 ,
'visible' => true ,
'required' => true ,
'user_defined' => true ,
'default' => '' ,
'searchable' => false ,
'filterable' => false ,
'comparable' => false ,
'visible_on_front' => false ,
'unique' => false ,
) ,
) ,
)
) ;
}
}

这里我们构建了一个数组,数组的元素是“key/value”对。“key”就是实体类型的名字(以下代码参数是一样的 “$installer->addEntityType(‘helloworld_eavblogpost’,…)”),“value”是一个数 组,用来描述这个实体类型。“value”数组的元素大部分你应该都见过,就不多解释了。这里要关注的是“attribute”元素,这个元素的值又是一 个数组。这个数组的内容就是我们定义的实体类型的属性,相当于普通数据表的列,比如这里的“title”。很可惜,我无法完整解释用来描述一个属性的数组 的内容。在这里,我们只要知道“type”就是这个属性的数据类型“varchar”。也就是说,这个属性的值将会被保存到 “eavblog_posts_varchar”数据表中。其他的很多元素都是和Magento的后台管理有关。Magento很多地方的UI是由模型控 制的,很多这些参数都是用来控制UI显示和系统设置。这样做的优点是灵活性提高,但是缺点是这些内容对于外部开发者都是不透明的。【译者注:我们是可以在 这个函数中返回多个实体类型的。如果返回多个实体类型,那就说明模块拥有多个模型。】

顺便说一下,Magento选择使用数组嵌套数组的形式来表示实体类型的属性很奇怪。因为Magento整个架构是非常面向对象的。这里的数据结构和系统的其他部分很不一样。

接下来我们需要修改安装脚本,添加如下代码

$installer
->
installEntities
(
)
;

“installEntities”会调用“getDefaultEntities”方法来获取将要被配置的属性。当然你也可以把属性直接作为参数 传给 “installEntities”,但是我觉得还是按照Magento的习惯来比较好。在调用“installEntitis”以后,Magento会 做下面两件事

  1. 在“eav_attribute”表中添加“title”属性
  2. 在“eav_entity_attribute”表中添加一行

清空Magento缓存,刷新页面,你应该看到如下异常

SQLSTATE[
23000
]
:
 Integrity constraint violation:
 1217
 Cannot delete or update a parent row:
 a foreign key
 constraint fails

那是因为我们之前已经调用过一次“createEntityTables”,再次调用的时候Magento会尝试先删除数据表,然后再创建。但是删 除的时 候Magento没有考虑到外键的关系,先尝试删除了主表,所以就有了以上异常。为了简化教程的例子,我们暂时把 “createEntityTables”语句删了。再次刷新页面,你应该看到正常的输出。

给EAV模型添加数据

到这里为止,我们的EAV模型已经创建好了,下面我们来为模型添加一些数据。在BlogController中添加以下方法

public
 function
 eavPopulateEntriesAction(
)
 {
 
for ( $i = 0 ; $i & lt; 10 ; $i ++ ) {
$weblog2 = Mage:: getModel ( 'helloworld-eav/eavblogpost' ) ;
$weblog2 -> setTitle ( 'This is a test ' . $i ) ;
$weblog2 -> save ( ) ;
}
echo 'Done' ;
}
public function eavShowcollectionAction( ) {
$weblog2 = Mage:: getModel ( 'helloworld-eav/eavblogpost' ) ;
$entries = $weblog2 -> getCollection ( ) -> addAttributeToSelect ( 'title' ) ;
$entries -> load ( ) ;
foreach ( $entries as $entry )
{
// var_dump($entry->getData());
echo '<h1>' . $entry -> getTitle ( ) . '</h1>' ;
}
echo '<br />Done<br />' ;
}

记得添加模型集合

class
 Wemvc_Helloworld_Model_Resource_Eav_Mysql4_Blogpost_Collection extends
 Mage_Eav_Model_Entity_Collection_Abstract 
{
protected function _construct( )
{
$this -> _init( 'helloworld-eav/eavblogpost' , 'helloworld-eav/blogpost' ) ;
}
}

访问以下URL

http:
//127.0.0.1/Magento/helloworld/blog/eavPopulateEntries

你应该看到正确的输出。细心一点的话你应该发现这里有两点比较特殊。第 一,“$weblog2->getCollection()->addAttributeToSelect(‘title’)”,这里的 “title”是干什么的?因为EAV模型在数据库层面比较复杂,一个简单的查询都需要好多个SQL才能完成。所以在查询的时候你需要指明你想找什么,这 样可以节省系统资源。不过你也可以传入“*”,表示查找所有数据。第二,为什么“$this->_init”有两个参数?在我们以前的章节中,简单 模型的模型集合初始化的时候只需要传入模型的URI就可以了,为什么这里要两个参数呢?其实如果你仔细看了模型集合抽象类的代码的话,你会发现这样一段

if
 (
is_null
(
$resourceModel
)
)
 {
 
$resourceModel = $model ;
}

所以其实是需要模型的URI和资源模型的URI,但是由于我们前面章节的例子,这两个URI是一样的,所以省略了第二个参数。而这里,资源模型的URI和模型的URI是不一样的,所以不能省略。

总结

到这里,你应该对Magento整个系统的运作有所了解了。起码下一次你看到网店里面的某个商品部显示了,或者什么属性不对了,你知道去哪里找问题。除了本章介绍的内容以外EAV模型还有很多东西可以学习。下面是我打算在以后的文章中介绍的一些内容

  1. EAV属性:EAV模型的属性类型不局限于datatime, decimal, int, text和varchar。你可以创建自定义的数据类型。
  2. 集合筛选:对EAV模型的数据进行筛选不是看起来的那么简单,特别是当属性是自定义类型的情况下,我们需要在集合装载之前调用“addAttributeToFilter”方法。
  3. Magento EAV模型继承:Magento在基本的EAV模型之上又创建了模型的继承关系,这些继承关系可以和网店的功能直接相关,也可以优化EAV模型的查询。

毫无疑问,EAV模型是Magento系统中最复杂的部分。不过你要始终相信一点,不管多复杂,它也就是程序。从哲学角度来讲,任何事物的产生都有特定的理由,你只需要搞清楚为什么。

来自: http://hi.baidu.com/190420456/blog/item/df74e845ae02ba8db2b7dc94.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值