magento教程第四章模型与ORM基础.docx

上传人:b****8 文档编号:10771632 上传时间:2023-02-22 格式:DOCX 页数:12 大小:22.42KB
下载 相关 举报
magento教程第四章模型与ORM基础.docx_第1页
第1页 / 共12页
magento教程第四章模型与ORM基础.docx_第2页
第2页 / 共12页
magento教程第四章模型与ORM基础.docx_第3页
第3页 / 共12页
magento教程第四章模型与ORM基础.docx_第4页
第4页 / 共12页
magento教程第四章模型与ORM基础.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

magento教程第四章模型与ORM基础.docx

《magento教程第四章模型与ORM基础.docx》由会员分享,可在线阅读,更多相关《magento教程第四章模型与ORM基础.docx(12页珍藏版)》请在冰豆网上搜索。

magento教程第四章模型与ORM基础.docx

magento教程第四章模型与ORM基础

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

深入理解Magento

作者:

AlanStorm

翻译:

HailongZhang

第四章–模型和ORM基础

对于任何一个MVC架构,模型(Model)层的实现都是占据了很大一部分。

对于Magento来说,模型占据了一个更加重要的位置,因为它常常包含了一部分商业逻辑代码(可以说它对,也可以说它错)。

这些代码在其他的MVC框架中往往出现在控制器或者帮助函数中。

传统的PHPMVC架构中的模型

本来MVC的定义就不是很清晰,不同的人有不同的看法,而对于模型的定义争议就更多了。

在MVC模式被广泛采用之前,PHP程序员往往通过SQL语句直接操作数据库。

也有些程序员通过一个SQL抽象层来操作数据库(比如AdoDB)。

程序员往往关注SQL语句本身,而不是和数据相关的对象。

虽然直接操作SQL的方式一直被病诟,但是很多PHP框架还是以SQL为中心的。

模型层提供了一系列对象,抽象/封装了数据操作,但是程序员最终还是需为模型层对象写SQL语句操作数据库。

还有一些框架回避了SQL,使用了对象关系映射(ObjectRelationalMapping,ORM)来解决这个问题。

使用这个方法的话,程序员不用关注SQL,而只需要和对象打交道。

我们可以操作一个对象的属性,当“Save”方法被调用的时候,对象的属性会作为数据自动的被写入数据库。

有些ORM框架会根据数据表的信息自动推测对象的属性,也有框架要求用户显示的生命对象属性和表的关系。

比较有名的ORM框架有ActiveRecord等等。

【译者注:

ActiveRecord源自RubyonRails,不过现在PHP也有了】

关于ORM的概念,我就解释到这里。

但是和许多计算机领域的其他概念一样,ORM的定义也越来越模糊了。

我不想在这片文章中讨论关于ORM的争议,所以我说的ORM就是那个最基本的ORM概念。

Magento的模型

Magento理所当然的也追随潮流应用了ORM。

虽然Magento自带的Zend框架提供了SQL抽象层,但是在大多数情况下我们将通过Magento自带的模型和我们自己的模型来进行数据访问。

他和视图层(View)一样,Magento的模型层也不是简单的ORM,而是一个高度灵活,高度抽象甚至有点令人费解。

解剖Magento的模型

大部分的Magento模型分为两类。

第一类是基本的ActiveRecord类型,一张表一个对象的模型。

第二类是EntityAttributeValue(EAV)模型。

【译者注:

EAV翻译成“实体属性值”有点词不达意,还是就叫EAV的好】Magento自己定义了一个数据类型叫做模型集合(ModelCollection)。

顾名思义,模型集合就是一个对象里面包含了很多模型对象。

Magento的创造者Varien团队实现了PHP类库的标准接口,“IteratorAggregate”,“Countable”。

这样模型集合就能调用这些方法,这也是模型集合和数组的区别。

Magento的模型并不直接访问数据库。

每一个模型都有一个资源模型(ResourceModel),每一个资源模型拥有两个适配器(Adapter),一个读,一个写。

这样的话逻辑模型和数据库访问就分开了,所以从理论上讲更改底层数据库只需要重写适配器就可以了,所有上层代码都不需要更改。

创建一个基本模型

【译者注:

从这一章开始我用我自己的例子替换了Alan的例子】继续我们HelloWorld的例子。

在HelloWorld模块中创建BlogController.php如下

classZhlmmc_Helloworld_BlogControllerextendsMage_Core_Controller_Front_Action{

publicfunctionindexAction()

{

echo'HelloBlog';

}

}

访问以下URL

http:

//127.0.0.1/Magento/helloworld/blog

你应该看到“HelloBlog”输出。

创建数据表

我们可以通过Magento自带的方法创建或者修改数据库,但是为了不引入过多新内容,我们暂且手工创建一张表。

在你的数据库中执行以下语句

CREATETABLE`blog_posts`(

`blogpost_id`int(11)NOTNULLauto_increment,

`title`text,

`post`text,

`date`datetimedefaultNULL,

`timestamp`timestampNOTNULLdefaultCURRENT_TIMESTAMP,

PRIMARYKEY(`blogpost_id`)

);

INSERTINTO`blog_posts`VALUES(1,'MyNewTitle','Thisisablogpost','2009-07-0100:

00:

00','2009-07-0223:

12:

30');

这里我们创建了一张名为“blog_posts”的表,并填充了一条数据。

创建模型

要设置一个模型一共有以下四个步骤

1启用模型

2启用资源模型

3在资源模型中添加实体(Entity)。

对于简单的模型来说,实体就是数据表的名字

4为资源模型设置读、写适配器

在进行这些步骤之前,我们先来看假设这些步骤已经做完了,我们怎么用一个模型。

在Magento中,我们用以下的方式来实例化一个模型

$model=Mage:

:

getModel('helloworld/blogpost');

和我们以前讲过的“Mage:

:

getHelper()”的原理类似,这里Magento也是通过全局配置去查找模型的类名。

模型的类名和我们以前讲过的块类名一样,都是分组类名。

这里参数的前半部分“helloworld”是组名(GroupName),后半部分“blogpost”是半类名(ClassName)【译者注:

我将“ClassName”翻译成半类名是为了和类名区分开来】。

具体步骤如下

5从全局配置“/global/models/GROUP_NAME/class”获得基本类名“Zhlmmc_Helloworld_Model”

6检查全局配置“/global/models/GROUP_NAME/rewrite/CLASS_NAME”是否设置,如果有那么这个节点的值将被作为类名实例化

7否则,最终的类名将是基本类名加上半类名,也就是“Zhlmmc_Helloworld_Model_Blogpost”

启用模型

修改模块的config.xml

--...-->

Zhlmmc_Helloworld_Model

--

needtocreateourownresource,can'tjust

usecore_mysql4

-->

helloworld_mysql4

--...-->

标签就是组名,也应该和模块名一致。

标签的内容是基本类名,所有Helloworld模块的模型都用这个基本类名,命名方式如下

Packagename_Modulename_Model

标签指明了这个模块的模型要用哪个资源模型。

这个标签的内容是组名加上“mysql4”我们将在后面详细介绍资源模型。

现在让我们来实例化一个模型看看,修改indexAction方法

publicfunctionindexAction(){

$blogpost=Mage:

:

getModel('helloworld/blogpost');

echoget_class($blogpost);

}

清空Magento缓存,刷新页面,你应该看到一个类似这样的异常(请先打开Magento的开发模式)

include(Zhlmmc\Helloworld\Model\Blogpost.php)[function.include]:

failedtoopenstream:

Nosuchfileordirectory

原因很简单,就是Magento尝试去实例化“Zhlmmc_Helloworld_Model_Blogpost”,但是它在Helloworld模块的文件夹里面找不到这个类。

所以我们现在来创建这个类

File:

app/code/local/Zhlmmc/Helloworld/Model/Blogpost.php

classZhlmmc_Helloworld_Model_BlogpostextendsMage_Core_Model_Abstract

{

protectedfunction_construct()

{

$this->_init('helloworld/blogpost');

}

}

刷新页面,你应该看到页面上显示“Zhlmmc_Helloworld_Model_Blogpost”。

所有的模型都必须继承“Mage_Core_Model_Abstract”类。

这个抽象类强制你实现一个方法“_construct”(注意:

这个不是PHP的构造行数“__construct”)。

这个方法应该调用父类已经定义好的“_init”方法,参数是资源模型的URI,也就是我们要告诉模型使用哪个资源模型。

我们将在解释资源模型的时候再解释这个URI。

启用资源模型并添加实体

好了,我们设置好了模型,下面我们要为模型设置资源模型。

资源模型才是真正和数据库对话的组件。

在模型的配置中,有一段这样的代码

helloworld_mysql4

的值将被用来实例化资源模型。

我们不需要显式的调用资源模型,但是当一个模型需要访问数据库的时候,Magento会自动实例化一个资源模型来使用。

Mage:

:

getResourceModel('helloworld/blogpost');

这里“helloworld/blogpost”就是我们给模型的“_init”传入的参数。

“helloworld”是组名,“blogpost”是模型的半类名。

“Mage:

:

getResourceModel”方法将以“helloworld/blogpost”为URI在全局配置中找到标签的值,在这里是“helloworld_mysql4”。

然后Magento会用URI“helloworld_mysql4/blogpost”去实例化资源模型类。

实例化的过程和我们前面讲的模型的实例化是一样的,所以我们也需要在config.xml中添加资源模型的声明

--...-->

--...-->

Zhlmmc_Helloworld_Model_Resource_Mysql4

这里我们可以看到,资源模型的声明也是放在下面的。

有点搞,但是也不必深究了,Magento就这么定义的。

标签的值是所有资源模型类的基本类名,命名方式如下

Packagename_Modulename_Model_Resource_Mysql4

好了,我们已经配置了资源模型,我们来试试装载一些数据。

修改indexAction如下

publicfunctionindexAction(){

$params=$this->getRequest()->getParams();

$blogpost=Mage:

:

getModel('helloworld/blogpost');

echo("LoadingtheblogpostwithanIDof".$params['id']."
");

$blogpost->load($params['id']);

$data=$blogpost->getData();

var_dump($data);

}

清空Magento缓存,访问下面的页面

http:

//127.0.0.1/Magento/helloworld/blog/index/id/1

你应该看到一个类似下面这样的异常

include(Zhlmmc\Helloworld\Model\Resource\Mysql4\Blogpost.php)[function.include]:

failedtoopenstream:

Nosuchfileordirectory

我想你看到这里也明白了,我们要为模型添加一个资源类,添加如下文件

File:

app/code/local/Zhlmmc/Helloworld/Model/Resource/Mysql4/Blogpost.php

classZhlmmc_Helloworld_Model_Resource_Mysql4_BlogpostextendsMage_Core_Model_Mysql4_Abstract{

protectedfunction_construct()

{

$this->_init('helloworld/blogpost','blogpost_id');

}

}

这里“_init”方法的第一个参数这个资源模型将要使用的数据表的URI,第二个参数是数据表中的列名。

这个列的内容必须唯一,往往是数据表的主键。

为资源模型添加实体

刷新页面,你是不是得到下面的异常?

Can'tretrieveentityconfig:

helloworld/blogpost

那是因为我们的资源文件现在还是一个空壳,并没有和数据库联系起来。

现在我们来把资源模型和我们的表联系起来,修改config.xml如下

--...-->

--...-->

Zhlmmc_Helloworld_Model_Resource_Mysql4

blog_posts

我们前面设置了资源模型使用的数据表的URI是“helloworld/blogpost”,那么Magento会把“helloworld”作为组名,“blogpost”作为实体名,也就是

在Magento的简单模型中(也就是继承Mage_Core_Model_Mysql4_Abstract的模型),一个实体对应一张数据表。

我们的数据表是“blog_posts”,所以这里

标签的内容就是“blog_posts”。

清空Magento缓存,再次刷新页面,你应该看到以下内容

LoadingtheblogpostwithanIDof1

array(5){["blogpost_id"]=>string

(1)"1"["title"]=>string(12)"MyNewTitle"["post"]=>string(19)"Thisisablogpost"["date"]=>string(19)"2009-07-0100:

00:

00"["timestamp"]=>string(19)"2009-07-0223:

12:

30"}

设置读写适配器

在上面的例子中,我们已经可以从数据库中取数据了,但是我们却没有为资源模型设置读写适配器,怎么回事呢?

原因很简单,那就是因为Magento会为没有适配器的资源模型启用默认适配器。

我们也可以显式的配置默认的适配器

--...-->

default_write

default_read

标签下面有两个部分,一个读,一个写。

标签名字中的“hellworld”是我们定义的组名【译者注:

在资源模型的“_init”函数中传入的数据表的URI“helloworld/blogpost”的前半部分就是适配器名字的前半部分】。

从这里我们也可以看出来一个资源组对应一对适配器。

清空Magento缓存,刷新浏览器,你应该看到和刚才相同的页面。

【译者注:

如果你去全局配置中找“core_read”你会发现“default_read”,然后是“default_setup”

mysql4

SETNAMESutf8

pdo_mysql

localhost

root

admin

zend-magento

1

这才是最终和数据库连接的详细信息。

如果你再往下深究,你会发现全局配置有这么一段

Mage_Core_Model_Resource_Type_Db_Pdo_Mysql

所以,“Mage_Core_Model_Resource_Type_Db_Pdo_Mysql”才是最终连接数据库的类。

如果我们更换数据库的话,我们要重写一个相似的类来连接别的数据库。

基本模型操作

所有的模型最终都继承自类“Varien_Object”。

这个类属于Magento的系统类库,不属于Magento的核心模块。

你可以在以下位置找到这个类

lib/Varien/Object.php

Magento模型的数据保存在“_data”属性中,这个属性是“protected”修饰的。

父类“Varian_Object”定义了一些函数用来取出这些数据。

我们上面的例子用了“getData”,这个方法返回一个数组,数组的元素是“key/value”对。

【译者注:

其实就是数据表中一行的数据,“key”就是列名,“value”就是值】我们可以传入一个参数获取某个具体的“key”的值。

$model->getData();

$model->getData('title');

还有一个方法是“getOrigData”,这个方法会返回模型第一次被赋予的值。

【译者注:

因为模型在初始化以后,值可以被修改,这个方法就是拿到那个最原始的值】

$model->getOrigData();

$model->getOrigData('title');

“Varien_Object”也实现了一些PHP的特殊函数,比如神奇的“__call”。

你可以对任何一个属性调用“get,set,unset,has”方法

$model->getBlogpostId();

$model->setBlogpostId(25);

$model->unsetBlogpostId();

if($model->hasBlogpostId()){...}

这里的方法名中的属性名字符合“camelcase”命名规则【译者注:

简单的说就是Java的命名规则,每个单词的第一个字母大写,第一个字母可以大写也可以小写】。

为了有效的利用这些方便的方法,我们在定义数据表列名的时候要用小写,并用下划线作为分隔符,比如“blogpost_id”。

在最近的Magento版本中,这个规则已经被弱化,为了实现PHP的“ArrayAccess”接口

$id=$model->['blogpost_id'];

$model->['blogpost_id']=25;

//etc...

也就是说,你会在Magento中同时看到这两种技巧的使用。

Magento中的CRUD操作

Magento模型通过“load,save,delete”三个方法来支持基本的Create,Read,Update和Delete操作。

我们在上面已经使用过“load”方法了。

这个方法的参数就是要装在的数据记录的“id”。

$blogpost->load

(1);

“save”方法可以用来创建新数据或者修改已有数据。

我们在BlogController.php中添加如下方法

publicfunctioncreateNewPostAction(){

$blogpost=Mage:

:

getModel('helloworld/blogpost');

$blogpost->setTitle('CodePost!

');

$blogpost->setPost('Thispostwascreatedfromcode!

');

$blogpost->save();

echo'postcreated';

}

访问以下URL

http:

//127.0.0.1/Magento/helloworld/blog/createNewPost

现在你数据表中应该有两条数据了。

下面来修改一条数据

publicfunctioneditFirstPostAction(){

$blogpost=Mage:

:

getModel('helloworld/blogpost');

$blogpost->load

(1);

$blogpost->setTitle("TheFir

展开阅读全文
相关搜索

当前位置:首页 > 解决方案 > 营销活动策划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1