第六章 – 高级Magento模型1

我们讲过Magento有两种模型,简单模型和EAV(Entity Attribute Value)模型。上一章我们讲过所有的Magento模型都是继承自Mage_Core_Model_Abstract / Varien_Object。简单模型和EAV模型的区别在于资源模型(Model Resource)。虽然所有的资源模型都最终继承“Mage_Core_Model_Resrouce_Abstract”,但是简单模型是直接继承 “Mage_Core_Model_Mysql4_Abstract”,而EAV模型是直接继承 “Mage_Eav_Model_Entity_Abstract”。

Magento这么做是由它的道理的。对于大部分开发人员或者用户来说,他们只需要知道一系列的方法能够操作模型,获得数据,数据到底是如何存储的并不是很重要。

 

什么是EAV模型?

Wikipedia是这么定义的:
EAV(Entity-Attribute-Value)模型,也作Object-Attribute-Value模型或者开放模型是一种数据模型。这种数据模型常常用在一个对象的属性数目不是一定的情况下。在数学上,这种模型称为松散矩阵。

换一种方式理解,EAV模型就是数据表的一种泛化。在传统的数据库中,数据表的列的数量是一定的

+
——————+
 
| products |
+ ——————+
| product_id |
| name |
| price |
| etc.. |
+ ——————+
+ ————+ —————-+ ——————+ ———+
| product_id | name | price | etc… |
+ ————+ —————-+ ——————+ ———+
| 1 | Widget A | 11.34 | etc… |
+ ————+ —————-+ ——————+ ———+
| 2 | Dongle B | 6.34 | etc… |
+ ————+ —————-+ ——————+ ———+

在上面这张表中,每一个商品都有名称,价格等等。

在EAV模型中,每一个模型都有不同的属性。这对于电子商务的应用来说是很合适的。比如说一个网店可以卖笔记本,拥有CPU速度,颜色,内存等属 性,但是 网店也可以卖衣服,有颜色属性,但是没有CPU速度。即使是卖衣服的网店,也有上衣和裤子之分,它们的属性也是不一样的。

有很多开源的或者商业的数据库是默认使用EAV模型的。但是一般的网站托管平台不提供这些数据库。所以Varien开发了一套基于PHP和MySQL的EAV系统。换句话说,它们在传统的关系型数据库上面开发了一套EAV数据库系统。

在使用的时候,EAV模型的属性是会分布在不同的MySQL数据表中。

上面的这张图是Magento中关于“catalog_product”的表。每一个产品都是“catalog_product_entity”中的一 行。Magento系统中所有的属性(不仅仅是商品)都存放在“eav_attribute”表中,而属性的值都放在类似下面的表中 “catalog_product_entity_attribute_varchar”, “catalog_product_entity_attribute_decimal”, “catalog_product_entity_attribute_etc”。【译者注:如果你仔细观察上面这幅数据表结构图,你会发现明显少了一张 表,和“entity_type”有关。因为这里有“entity_type_id”出现,但却没有定义这个属性的表。这个表在Magneto中叫做 “eav_entity_type”。由于EAV模型中所有的模型数据都混在一套数据表中了,实体类型(entity_type)就是用来把不同的模型区 别开来的属性。假如我们要找出系统中所有的产品数据,那么Magento先通过“eav_entity_type”表获得产品模型的 “entity_type_id”,然后再通过上面这幅图的关系来拿到所有的数据。

在EAV系统下面,当你需要添加一个属性的时候,只需要在“eav_attribute”表中添加一行就行了。而传统的关系型数据库则需要修改数据 表调用 “ALTER TABLE”语句,复杂而且有风险。EAV模型的缺点是你不能通过一个简单的SQL语句就获得一个模型的所有属性。你往往需要调用多个SQL或者一个 SQL包干了多个join语句。

实战EAV模型

我们已经介绍了EAV是怎么工作的了。下面我们要通过一个例子来说明要在Magento中创建一个EAV模型所需要的步骤。这部分内容大概是 Magento中最令人头疼的部分,95%的Magento用户都不会和这些代码打交道,但是理解EAV模型的原理能够帮助你更好的理解Magento的 代码和架构。

因为EAV模型的内容太多了,所以我假设你已经熟悉了前几章的内容,包括Magento MVC,组类名等等。在这一章我不会再重复这些内容。

EAV形式的Hello World

我们将为Hello World模块创建另外一个模型,使用EAV形式的资源模型。首先我们为模块创建一个新的模型叫做“Eavblogpost”。记住,简单模型和EAV模型的区别是资源模型,所以我们创建一个模型的基本步骤是一样的。

<
global>
 
< ! – … –>
< models>
< ! – … –>
< helloworld- eav>
< class> Wemvc_Helloworld_Model</ class>
< resourceModel> helloworld- eav_mysql4</ resourceModel>
</ helloworld- eav>
< ! – … –>
</ models>
< ! – … –>
</ global>

我想我不说你也应该知道,我们要创建一个新的模型文件。由于PHP 5.3和命名空间(namespaces)还没有被广泛采用,Magento中的类名仍然和文件的物理路径相关。这就导致了很多时候不知道一个URI所对 应的类究竟该放在什么文件夹下面。我发现我们可以利用Magento的异常信息来直接得到一个类的路径。比如,这里我们先不创建模型类,先来修改 BlogController来直接使用模型类,这样Magento就会报错说找不到模型类,并给出路径

public
 function
 eavReadAction(
)
{
 
$eavModel = Mage:: getModel ( 'helloworld/eavblogpost' ) ;
echo get_class ( $eavModel ) . "<br />" ;
}

清空Magento缓存,访问以下URL

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

跟预计的一样,你应该得到以下异常

Warning:
 include
(
Wemvc/
Helloworld/
Model/
Eavblogpost.
php)
 [
function
.
include
]
:
 failed to open stream:
 No such file
 or directory

所以我们应该创建如下文件

File
:
 app/
code/
local/
Wemvc/
Helloworld/
Model/
Eavblogpost.
php 
class Wemvc_Helloworld_Model_Eavblogpost extends Mage_Core_Model_Abstract
{
protected function _construct( )
{
$this -> _init( 'helloworld-eav/blogpost' ) ;
}
}

刷新页面,你应该看到下面的输出

Wemvc_Helloworld_Model_Eavblogpost

下面我们来创建资源模型。先定义资源模型

<
helloworld-
eav_mysql4>

< class> Wemvc_Helloworld_Model_Resource_Eav_Mysql4</ class>
< entities>
< blogpost>
< table> eavblog_posts</ table>
</ blogpost>
</ entities>
</ helloworld- eav_mysql4>

这里的标签名字和我们上面定义的模型的是一致的。的定义和上一章是一样的。下面的适配器的定义

<
resources>
 
< ! – … ->
< helloworld- eav_write>
< connection>
< use> default_write</ use>
</ connection>
</ helloworld- eav_write>
< helloworld- eav_read>
< connection>
< use> default_read</ use>
</ connection>
</ helloworld- eav_read>
</ resources>

然后再次利用Magento的异常,先修改“eavReadAction”

public
 function
 eavReadAction(
)
{
 
$eavModel = Mage:: getModel ( 'helloworld-eav/eavblogpost' ) ;
$params = $this -> getRequest ( ) -> getParams ( ) ;
echo ( "Loading the blogpost with an ID of " . $params [ 'id' ] . "<br />" ) ;
$eavModel -> load ( $params [ 'id' ] ) ;
$data = $eavModel -> getData ( ) ;
var_dump ( $data ) ;
}

清空Magento缓存,访问URL

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

你应该看到如下异常

Warning:
 include
(
Wemvc/
Helloworld/
Model/
Resource/
Eav/
Mysql4/
Blogpost.
php)
 [
function
.
include
]
:
 failed to open stream:
 No such file
 or directory

所以我们创建相应的资源模型类

File
:
 app/
code/
local/
Wemvc/
Helloworld/
Model/
Resource/
Eav/
Mysql4/
Blogpost.
php 
class Wemvc_Helloworld_Model_Resource_Eav_Mysql4_Blogpost extends Mage_Eav_Model_Entity_Abstract
{
public function _construct( )
{
$resource = Mage:: getSingleton ( 'core/resource' ) ;
$this -> setType ( 'helloworld_eavblogpost' ) ;
$this -> setConnection (
$resource -> getConnection ( 'helloworld-eav_read' ) ,
$resource -> getConnection ( 'helloworld-eav_write' )
) ;
}
}

这个类和简单的资源模型就不一样。首先,我们这里继承的是“Mage_Eav_Model_Entity_Abstract”。其次,我们没有调用 “_init”方法。在EAV模型中我们需要自己来完成资源模型初始化的过程,包括,告诉资源模型使用哪个适配器,以及实体类型 (entity_type)。刷新URL,你应该看到如下异常

Invalid entity_type specified:
 helloworld_eavblogpost

根据我们上文所讲的内容,那这个异常的原因很明显,那就是“eav_entity_type”表中,没有需要的 “helloworld_eavblogpost”的数据。这里的“helloworld_eavblogpost”就是我们“setType”的参数。 让我们来看一下这张表长什么样

mysql>
 select *
 from eav_entity_type/G 
*************************** 1. row ***************************
entity_type_id: 1
entity_type_code: customer
entity_model: customer/ customer
attribute_model:
entity_table: customer/ entity
value_table_prefix:
entity_id_field:
is_data_sharing: 1
data_sharing_key: default
default_attribute_set_id: 1
increment_model: eav/ entity_increment_numeric
increment_per_store: 0
increment_pad_length: 8
increment_pad_char: 0
additional_attribute_table: customer/ eav_attribute
entity_attribute_collection: customer/ attribute_collection
*************************** 2. row ***************************
entity_type_id: 2
entity_type_code: customer_address
entity_model: customer/ customer_address
attribute_model:
entity_table: customer/ address_entity
value_table_prefix:
entity_id_field:
is_data_sharing: 1
data_sharing_key: default
default_attribute_set_id: 2
increment_model:
increment_per_store: 0
increment_pad_length: 8
increment_pad_char: 0
additional_attribute_table: customer/ eav_attribute
entity_attribute_collection: customer/ attribute_collection

正如我们前面讲过的,这张表包含了所有系统中的实体类型。我们的参数“helloworld_eavblogpost”就是实体类型的值,对应数据表列“entity_type_code”。

系统和应用程序

这一章讲的内容是Magento最重要的一个概念,也是很多人觉得头疼的概念。拿电脑来做比方。操作系统,比如Mac OS X,Windows,Linux等等,是软件系统,而浏览器,比如FIrefox,Safari,IE等等是应用程序。Magento首先是一个系统,其 次才是一个应用程序。你可以在Magento系统之上创建一个电子商务应用。令人感到困惑的是Magento的代码在很多地方是以很原始的方式暴露给应用 程序的。EAV系统的配置和你网店的数据存放在统一数据库中就是一个例子。

随着你越来越深入Magento,你需要把Magento当作老式的 IBM 650 机器。也就是说,你必须对Magento有很深的了解才能对它运用自如。【译者注:这一段和上下文没什么关系,大概是作者有感而发】

创建资源配置

从理论上讲,你可以手动的在数据库中插入数据,让我们的EAV模型工作,但我还是不建议你这么做。所幸的是,Magento提供了一个特殊的资源配置类,包含了一些有用的方法能自动的创建一些数据,使得系统能工作。

我们先添加资源配置

<
resources>
 
< ! – … –>
< helloworld- eav_setup>
< setup>
< module> Wemvc_Helloworld</ module>
< class> Wemvc_Helloworld_Model_Entity_Setup</ class>
</ setup>
< connection>
< use> core_setup</ use>
</ connection>
</ helloworld- eav_setup>
< ! – … –>
</ resources>

创建资源配置类文件

File
:
 app/
code/
local/
Wemvc/
Helloworld/
Model/
Entity/
Setup.
php 
class Wemvc_Helloworld_Model_Entity_Setup extends Mage_Eav_Model_Entity_Setup {
}

请注意,这里我们继承的父类是“Mage_Eav_Model_Entity_Setup”。最后,我们来创建安装脚本。如果你不熟悉这部分内容,请你参考前面章节的内容。

File
:
 app/
code/
local/
Wemvc/
Helloworld/
sql/
helloworld-
eav_setup/
mysql4-
install-
0.
1.
0.
php 
< ?php
$installer = $this ;
throw new Exception( "This is an exception to stop the installer from completing" ) ;
?>

清空Magento缓存,访问任何页面,你应该看到以上异常。如果你没有看到异常,那说明你哪里配置错了。

请注意:我们将一步一步的创建安装脚本。如果你阅读了前面的章节,你应该知道我们必须删除“core_resource”数据表中的相应数据才能使 得安装 脚本重新运行。所以在我们下面的例子中,当我们修改了安装脚本,我们都默认会删除“core_resource”表中的数据。正常使用Magento的时 候我们不需要这样做的,教程中的例子是极端情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值