Magento模块开发手册(五)Magento模型和ORM基础



对于任何一个MVC 架构,模型(Model)层的实现都是占据了很大一部分。对于 Magento来说,模型占据了一个更加重要的位置,因为它常常包含了一 部分商业逻辑代码(可以说它对,也可以说它错)。这些代码在其他的MVC框架中往往出现在控制器或者帮助函数中。

传统的PHP MVC模型

本来 MVC的定义就不是很清晰,不同的人有不同的看法,而对于模型的定义争议就更多了。在 MVC模式被广泛采用之前,PHP程序员往往通过 SQL语句直接 操作数据库。也有些程序员通过一个SQL 抽象层来操作数据库(比如AdoDB)。程序员往往关注 SQL语句本身,而不是和数据相关的对象。

虽然直接操作 SQL的方式一直被病诟,但是很多 PHP框架还是以SQL 为中心的。模型层提供了一系列对象,抽象/封装了数据操作,但是程序员最终还是需为模型层对象写 SQL语句操作数据库。

还有一些框架回避了SQL,使用了对象关系映射(Object Relational Mapping,ORM)来解决这个问题。使用这个方法的话,程序员不用关注SQL,而只需要和对象打交道。我们可以操作一个对象的属性,当“Save” 方法被调用的时候,对象的属性会作为数据自动的被写入数据库。有些 ORM框架会根据数据表的信息自动推测对象的属性,也有框架要求用户显示的生命对象属性 和表的关系。比较有名的ORM框架有ActiveRecord等等。【注:ActiveRecord源自Ruby onRails,不过现在 PHP也有了】

关于ORM 的概念,我就解释到这里。但是和许多计算机领域的其他概念一样,ORM的定义也越来越模糊了。我不想在这片文章中讨论关于 ORM的争议,所以我说的ORM就是那个最基本的 ORM概念。

Magento模型

Magento 理所当然的也追随潮流应用了ORM。虽然 Magento自带的 Zend框架提供了SQL 抽象层,但是在大多数情况下我们将通过 Magento自带的模型和我们自己的模型来进行数据访问。他和视图层(View)一样,Magento的模型层也不是简单的 ORM,而是一个高度灵活, 高度抽象甚至有点令人费解。

Magento的模型解剖

大部分的 Magento模型分为两类。第一类是基本的 ActiveRecord类型,一张表一个对象的模型。第二类是Entity Attribute Value(EAV)模型。【译者注:EAV翻译成“实体属性值”有点词不达意,还是就叫 EAV的好】Magento 自己定义了一个数据类型叫做模型集合 (Model Collection)。顾名思义,模型集合就是一个对象里面包含了很多模型对象。Magento 的创造者Varien团队实现了PHP类库的标准接 口,“IteratorAggregate”,“Countable”。这样模型集合就能调用这些方法,这也是模型集合和数组的区别。

Magento 的模型并不直接访问数据库。每一个模型都有一个资源模型(ResourceModel),每一个资源模型拥有两个适配器(Adapter),一个读,一个写。这样的话逻辑模型和数据库访问就分开了,所以从理论上讲更改底层数据库 只需要重写适配器就可以了,所有上层代码都不需要更改。

创建基本模型

下面我们开始创建一个基础的Magento模型,我们以简单的weblog博客为例,构建一个模型,总的分为以下几步。

  1. 创建一个新的“Weblog”模块
  2. 为我们的模型创建一个数据库表
  3. 添加模型信息到配置,模型命名为Blogpost
  4. 为我们的Blogpost模型添加模型资源信息到配置文件
  5. 为我们的Blogpost模型添加一个读取适配器(Read Adapter)到配置文件
  6. 为我们的Blogpost模型添加写入适配器(Write Adapter)到配置文件
  7. 为Blogpost模型添加一个PHP类文件
  8. 为Blogpost资源模型添加一个PHP类文件
  9. 实例化模型

创建一个Weblog 模块

通过之前几节的学习,创建一个新的空模块应该没有问题啦,这里我们跳过这些细节,假设你已经创建了一个名为Weblog的空模块。完成之后,我们为Index控制器设置路由规则。这里依然假设我们的Package命名为Magentotutorial。

在 Magentotutorial/Weblog/etc/config.xml, 设置一下路由

然后添加以下内容到动作控制器(at Magentotutorial/Weblog/controllers/IndexController.php)中

清空Magento缓存和加载下面的URL,以确保一切都正确安装了。

您应该看到在白色背景上的单词“设置”。

 

创建数据库表

Magento的具有自动创建和修改数据库架构的系统,但暂时我们只能为我们的模型手动创建一个表。

使用命令行或您最喜爱的的MySQL GUI应用程序,创建一个表按下面的架构

然后用一些数据来填充它

 

全局配置和创建模型

我们要在配置文件里面设置一个模型有五个步骤。

  1. 在模块中启用模型
  2. 在模块中启用模型资源(Model Resources)
  3. 添加一个“实体”表配置到我们的模型资源。.

这是你可以实例化的magento的模型,你可以这样写

 

getmodel()方法里的URI的第一部分叫做模型组名(Model Group Name)。考虑到Magento为类使用__autoload方法,所以该模型组名必须是模块的小写形式。该URI的第二部分是你的模型名的小写形式。

所以,让我们添加下面的XML到我们的模块的config.xml。

最外层的<weblog />标签是模型组名,应该匹配模块名。<class />中的值是weblog组中所有的模型都拥有的BASE名。<resourceModel />标签指定weblog组中的模型应该使用哪种模型资源,这里我们先记得它是由模型组名加“mysql4”。

S所以,我们还没有完成,但让我们看看如果我们清除我们的Magento缓存,试图实例化blogpos模型会发生什么。在你的testModelAction方法,使用下面的代码

并重新加载页面。你应该看到一个异常,看起来像这样(确保你已经打开了开发模式)。

由于在上面那段代码中,试图引用‘weblog/blogpost’模型,Magento会实例化下面这个类,

Magento试图自动加载这个模型,但是无法找到该文件。让我们创造它!在以下位置创建以下类(Magento的试图加载的这个模型),但是无法找到该文件。让我们创造它!在以下位置创建以下类

刷新页面之后,异常就被该类名所取代了。

与数据库交互的所有基本模型都必须继承 “Mage_Core_Model_Abstract”类。这个抽象类强制你实现一个方法命名_construct(注意:这不是PHP的构造函数__construct)。这个方法应该调用父类已经定义好的“_init”方法,参数是资源模型的 URI,也就是我们要告诉模型使用哪个资源模型。 我们将在解释资源模型的时候再解释这个URI。

 

全局配置和模型资源

因此,我们已经建立了模型。接下来,我们需要设置我们的模型资源。模型包含的资源,实际上会谈到我们的数据库的代码。在上一小节中,我们在配置文件中添加了如下配置。

在<resourceModel />中的值会实例化一个模型资源类。尽管你从不需要手动调用它,当任何在weblog组中的模型需要与数据库交互时,Magento会调用以下方法获取模型资源。

再次强调,weblog是模型组名,blogpost是模型名。Mage::getResourceModel方法使用weblog/blogpost URI来检查全局配置文件,并获取<resourceModel>中的值(在这里,是weblog_resource)。然后,下列URI地址的模型类将会被实例化。

所以,如果你遵循了所有的方式,这是什么意思,资源模型的配置与模型的配置在XML配置文件中的相同节点。这可能会造成混淆。

因此,考虑到这一点,让我们配置我们的资源。在我们的<models>部分添加

这里设置的<weblog_resource />标签,就是刚刚在<resourceModel />标签中设置的值。<class />节点中的值是使用的资源模型的基础命名,它的命名方式大概如下

因此,我们有一个配置的资源,让我们试着装了一些模型数据。改变你的action,如下所示

然后在浏览器加载下面的URL(清除Magento缓存后)

你应该可以看到一个异常像下面这样

正如你的直觉,我们需要为我们的模型添加一个资源类。每种模型都有其自身的资源类。添加以下类在以下位置

这里“_init”方法的第一个参数这个资源模型将要使用的数据表的URI,第二个参数是数据表中的列名。这个列的内容必须唯一,往往是数据表的主键。清除缓存,重新加载,你应该会看到

另一个例外!当我们使用模型的URI weblog/blogpost,我们将告诉Magento的,我们想要的模型组的weblog,,以及blogpost的实体。在扩展Mage_Core_Model_Resource_Db_Abstract简单的模型的背景下,一个实体对应一个表。在这种情况下,我们上面创建表名为blog_post。让我们加入实体到我们的XML配置文件。

我们增加了一个新的<entities />节点给我们配置的资源模型部分。这反过来,有我们的entity (<blogpost />)命名的部分,用于指定要使用此模型的数据库表的名称。

清空Magento缓存,用你的手指,重新加载页面,…

找到了!我们已经成功地提取了数据,更重要的是,完全配置了一个Magento的模型。

 

基础的Magento模型操作

所有的Magento模型继承了Varien_Object类。这个类是Magento的系统库的一部分,而不是Magento核心模块的一部分。您可以在此找到对象

Magento模型将数据保存在一个protected的_data属性中。Varien_Object类提供给我们很多方法,可以使用这些方法读取这些 数据。你已经使用过了getData()方法,该方法返回一个包含字段/值的数组。你也可以通过传递字段名作为该方法的参数来获取相应字段的值

还有一个getOrigData方法,该方法将返回模型数据,因为它最初是在填充物中,(以protected _origData方式工作)。

Varien_Object类通过PHP的魔术方法__call实现了一些特殊的方法。你可以通过get,set,unset以及has加上驼峰命名的字段名的方式,获取、设置、unset及查看任意存在的字段值。

正因为如此,你可能会以小写字母及下划线来命名数据库字段。不过,最近版本的Magento已经舍弃了这种语法,转而实现PHP的数组连接(ArrayAccess)接口。

 

Magento的CRUD操作

Magento模型支持基本的创建,读取,更新和删除的CRUD功能与加载,保存和删除的方法。你已经看到了正在运行的负载的方法。当传递一个参数,负载方法会返回一个记录的id字段(在模型的资源集)匹配传入的值。

save()方法允许你插入新数据到模型中,或更新已经存在的数据。添加如下代码到控制器中。

然后通过加载下面的URL执行你的控制器动作

这时你会看到数据库表中新增了一条数据,接下来,请尝试以下操作来编辑您的文章

最后,你可以用非常相似的语法删除自己的帖子。

模型集合(Model Collections)

对于单独一个模型的操作固然很有用,但是多数时候,我们会同时操作多个模型。比返回多个模型的一个多维嵌套数组更好的是,在Magento中,每个模型类 型都有一个唯一的收集对象与其关联。这些对象实现了PHP IteratorAggregate和Countable接口,这意味着它们可以被传递到count函数,并使用for each结构循环出数据。

我们将在后面具体介绍Magento的收集机制,现在我们先简要介绍下它的设置和使用。添加如下代码到控制器中,然后再浏览器中访问该地址。

加载操作URL,

你应该看到一个(现在)熟悉的警告。

你不感到惊讶,是吗?我们需要添加一个类来定义Blogpost的模型收集。每个模型资源拥有一个_resourceCollectionName保护属性,它包含了用来识别收集的URI。

默认情况下,该URI也用来识别模型资源,以字符串”_collection”结尾。Magento将收集归为模型资源的一部分,所以该URI转换为类名之后如下,

添加下面的PHP类在以下位置

 

和其他类一样,我们需要使用该模型的URI(weblog/blogpsot)来_init模型收集。最后,在浏览器中访问模型收集的地址,就能成功返回文章的数据信息了。

 

结束语

恭喜你,你已经创建并配置了你的Magento模型。在后面的文章中,我们将看看Magento的实体属性值模型(EAV),它将更深入了我们在这里学到的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值