`
coolsooner
  • 浏览: 1363953 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多
深入理解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 on Rails,不过现在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的模型并不直接访问数据库。每一个模型都有一个资源模型(Resource Model),每一个资源模型拥有两个适配器(Adapter),一个读,一个写。这样的话逻辑模型和数据库访问就分开了,所以从理论上讲更改底层数据库只需要重写适配器就可以了,所有上层代码都不需要更改。 创建一个基本模型 继续我们Hello World的例子。在Hello World模块中创建BlogController.php如下 class App_Helloworld_BlogController extends Mage_Core_Controller_Front_Action { public function indexAction() { echo 'Hello Blog'; } } 访问以下URL http://127.0.0.1/Magento/helloworld/blog 你应该看到“Hello Blog”输出。 创建数据表 我们可以通过Magento自带的方法创建或者修改数据库,但是为了不引入过多新内容,我们暂且手工创建一张表。在你的数据库中执行以下语句 CREATE TABLE `blog_posts` ( `blogpost_id` int(11) NOT NULL AUTO_INCREMENT, `title` text, `post` text, `date` datetime DEFAULT NULL, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`blogpost_id`) ); INSERT INTO `blog_posts` VALUES (1,'My New Title','This is a blog post','2009-07-01 00:00:00','2009-07-02 23:12:30'); 这里我们创建了一张名为“blog_posts”的表,并填充了一条数据。 创建模型 要设置一个模型一共有以下四个步骤 1. 启用模型 2. 启用资源模型 3. 在资源模型中添加实体(Entity)。对于简单的模型来说,实体就是数据表的名字 4. 为资源模型设置读、写适配器 在进行这些步骤之前,我们先来看假设这些步骤已经做完了,我们怎么用一个模型。在Magento中,我们用以下的方式来实例化一个模型 $model = Mage::getModel('helloworld/blogpost'); 和我们以前讲过的“Mage::getHelper()”的原理类似,这里Magento也是通过全局配置去查找模型的类名。模型的类名和我们以前讲过的块类名一样,都是分组类名。这里参数的前半部分“helloworld”是组名(Group Name),后半部分“blogpost”是半类名(Class Name)【注:我将“Class Name”翻译成半类名是为了和类名区分开来】。具体步骤如下 1. 从全局配置“/global/models/GROUP_NAME/class”获得基本类名“App_Helloworld_Model” 2. 检查全局配置“/global/models/GROUP_NAME/rewrite/CLASS_NAME”是否设置,如果有那么这个节点的值将被作为类名实例化 3. 否则,最终的类名将是基本类名加上半类名,也就是“App_Helloworld_Model_Blogpost” 启用模型 修改模块的config.xml <global><!-- ... --><models><helloworld><class>App_Helloworld_Model</class><!-- need to create our own resource, can't just use core_mysql4 --><resourcemodel>helloworld_mysql4</resourcemodel></helloworld></models><!-- ... --></global> 标签就是组名,也应该和模块名一致。标签的内容是基本类名,所有Helloworld模块的模型都用这个基本类名,命名方式如下 Packagename_Modulename_Model 标签指明了这个模块的模型要用哪个资源模型。这个标签的内容是组名加上“mysql4”我们将在后面详细介绍资源模型。 现在让我们来实例化一个模型看看,修改indexAction方法 public function indexAction() { $blogpost = Mage::getModel('helloworld/blogpost'); echo get_class($blogpost); } 清空Magento缓存,刷新页面,你应该看到一个类似这样的异常(请先打开Magento的开发模式) include(App/Helloworld/Model/Blogpost.php) [function.include]: failed to open stream: No such file or directory 原因很简单,就是Magento尝试去实例化“App_Helloworld_Model_Blogpost”,但是它在Helloworld模块的文件夹里面找不到这个类。所以我们现在来创建这个类 File: app/code/local/App/Helloworld/Model/Blogpost.php class App_Helloworld_Model_Blogpost extends Mage_Core_Model_Abstract { protected function _construct() { $this->_init('helloworld/blogpost'); } } 刷新页面,你应该看到页面上显示”App_Helloworld_Model_Blogpost”。所有的模型都必须继承“Mage_Core_Model_Abstract”类。这个抽象类强制你实现一个方法“_construct”(注意:这个不是PHP的构造行数“__construct”)。这个方法应该调用父类已经定义好的“_init”方法,参数是资源模型的URI,也就是我们要告诉模型使用哪个资源模型。我们将在解释资源模型的时候再解释这个URI。 启用资源模型并添加实体 好了,我们设置好了模型,下面我们要为模型设置资源模型。资源模型才是真正和数据库对话的组件。在模型的配置中,有一段这样的代码 <resourcemodel>helloworld_mysql4</resourcemodel> 的值将被用来实例化资源模型。我们不需要显式的调用资源模型,但是当一个模型需要访问数据库的时候,Magento会自动实例化一个资源模型来使用。 Mage::getResourceModel('helloworld/blogpost'); 这里“helloworld/blogpost”就是我们给模型的“_init”传入的参数。“helloworld”是组名,“blogpost”是模型的半类名。“Mage::getResourceModel”方法将以“helloworld/blogpost”为URI在全局配置中找到标签的值,在这里是“helloworld_mysql4”。然后Magento会用URI“helloworld_mysql4/blogpost”去实例化资源模型类。实例化的过程和我们前面讲的模型的实例化是一样的,所以我们也需要在config.xml中添加资源模型的声明 <global><!-- ... --><models><!-- ... --><helloworld_mysql4><class>App_Helloworld_Model_Resource_Mysql4</class></helloworld_mysql4></models></global> 这里我们可以看到,资源模型的声明也是放在下面的。有点搞,但是也不必深究了,Magento就这么定义的。标签的值是所有资源模型类的基本类名,命名方式如下 Packagename_Modulename_Model_Resource_Mysql4 好了,我们已经配置了资源模型,我们来试试装载一些数据。修改indexAction如下 public function indexAction() { $params = $this->getRequest()->getParams(); $blogpost = Mage::getModel('helloworld/blogpost'); echo("Loading the blogpost with an ID of ".$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(App/Helloworld/Model/Resource/Mysql4/Blogpost.php) [function.include]: failed to open stream: No such file or directory 我想你看到这里也明白了,我们要为模型添加一个资源类,添加如下文件 File: app/code/local/App/Helloworld/Model/Resource/Mysql4/Blogpost.php class App_Helloworld_Model_Resource_Mysql4_Blogpost extends Mage_Core_Model_Mysql4_Abstract{ protected function _construct() { $this->_init('helloworld/blogpost', 'blogpost_id'); } } 这里“_init”方法的第一个参数这个资源模型将要使用的数据表的URI,第二个参数是数据表中的列名。这个列的内容必须唯一,往往是数据表的主键。 为资源模型添加实体 刷新页面,你是不是得到下面的异常? Can't retrieve entity config: helloworld/blogpost 那是因为我们的资源文件现在还是一个空壳,并没有和数据库联系起来。现在我们来把资源模型和我们的表联系起来,修改config.xml如下 <global><!-- ... --><models><!-- ... --><helloworld_mysql4><class>App_Helloworld_Model_Resource_Mysql4</class><entities><blogpost><table>blog_posts</table></blogpost></entities></helloworld_mysql4></models></global> 我们前面设置了资源模型使用的数据表的URI是“helloworld/blogpost”,那么Magento会把“helloworld”作为组名,“blogpost”作为实体名,也就是。在Magento的简单模型中(也就是继承Mage_Core_Model_Mysql4_Abstract的模型),一个实体对应一张数据表。我们的数据表是“blog_posts”,所以这里 标签的内容就是“blog_posts”。 清空Magento缓存,再次刷新页面,你应该看到以下内容 Loading the blogpost with an ID of 1 array(5) { ["blogpost_id"]=> string(1) "1" ["title"]=> string(12) "My New Title" ["post"]=> string(19) "This is a blog post" ["date"]=> string(19) "2009-07-01 00:00:00" ["timestamp"]=> string(19) "2009-07-02 23:12:30" } 设置读写适配器 在上面的例子中,我们已经可以从数据库中取数据了,但是我们却没有为资源模型设置读写适配器,怎么回事呢?原因很简单,那就是因为Magento会为没有适配器的资源模型启用默认适配器。我们也可以显式的配置默认的适配器 <global><!-- ... --><resources><helloworld_write><connection><use>default_write</use></connection></helloworld_write><helloworld_read><connection><use>default_read</use></connection></helloworld_read></resources></global> 在标签下面有两个部分,一个读,一个写。标签名字中的“hellworld”是我们定义的组名【注:在资源模型的“_init”函数中传入的数据表的URI “helloworld/blogpost”的前半部分就是适配器名字的前半部分】。从这里我们也可以看出来一个资源组对应一对适配器。清空Magento缓存,刷新浏览器,你应该看到和刚才相同的页面。【注:如果你去全局配置中找“core_read”你会发现“default_read”,然后是“default_setup” <default_setup><connection><model>mysql4</model><initstatements>SET NAMES utf8</initstatements><type>pdo_mysql</type><host>localhost</host><username>root</username><password>admin</password><dbname>zend-magento</dbname><active>1</active></connection></default_setup> 这才是最终和数据库连接的详细信息。如果你再往下深究,你会发现全局配置有这么一段 <resource><connection><types><pdo_mysql><class>Mage_Core_Model_Resource_Type_Db_Pdo_Mysql</class></pdo_mysql></types></connection></resource> 所以,“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中添加如下方法 public function createNewPostAction() { $blogpost = Mage::getModel('helloworld/blogpost'); $blogpost->setTitle('Code Post!'); $blogpost->setPost('This post was created from code!'); $blogpost->save(); echo 'post created'; } 访问以下URL http://127.0.0.1/Magento/helloworld/blog/createNewPost 现在你数据表中应该有两条数据了。下面来修改一条数据 public function editFirstPostAction() { $blogpost = Mage::getModel('helloworld/blogpost'); $blogpost->load(1); $blogpost->setTitle("The First post!"); $blogpost->save(); echo 'post edited'; } 最后,我们来删除一条数据 public function deleteFirstPostAction() { $blogpost = Mage::getModel('helloworld/blogpost'); $blogpost->load(1); $blogpost->delete(); echo 'post removed'; } 模型集合 上面的例子我们只是演示了对单个数据操作,现在我们来看看如何同时操作多条记录。我们上面已经讲过,每个Magento的模型都有一个独特的模型集合。这些模型集合实现了PHP的“IteratorAggregate”和“Countable”接口,也就是他们可以作为“count”函数的参数,并且可以在“for each”语句中使用。 现在让我们来看看如何使用模型集合,在Blog控制器中添加如下方法 public function showAllBlogPostsAction() { $posts = Mage::getModel('helloworld/blogpost')->getCollection(); foreach($posts as $blog_post){ echo '

'.$blog_post->getTitle().'

'; echo nl2br($blog_post->getPost()); } } 访问如下URL http://127.0.0.1/Magento/helloworld/blog/showAllBlogPosts 你应该看到以下异常 include(App/Helloworld/Model/Resource/Mysql4/Blogpost/Collection.php) [function.include]: failed to open stream: No such file or directory 我想你不会被这个异常吓到,已经熟门熟路了。我们需要添加一个PHP类,定义Blogpost的模型集合。每个模型都有一个“protected”属性“_resourceCollectionName”【注:从父类“Mage_Core_Model_Abstract”继承来的】。这个属性的值是这个模型对应的模型集合的URI。 protected '_resourceCollectionName' => string 'helloworld/blogpost_collection' 在默认情况下,这个值是模型的URI加上“_collection”。Magento把模型集合也看做是一种资源(Resrouce),所以运用资源模型的命名规则,模型集合的全名是 App_Helloworld_Model_Resource_Mysql4_Blogpost_Collection 然后我们要创建如下文件 File: app/code/local/App/Helloworld/Model/Resource/Mysql4/Blogpost/Collection.php class App_Helloworld_Model_Resource_Mysql4_Blogpost_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract { protected function _construct() { $this->_init('helloworld/blogpost'); } } 这里的参数是模型的UR,用来I来初始化模型集合。刷新页面,你应该看到数据库中的Blog都显示出来了。 总结 首先我要恭喜你,到这里你已经创建并配置了你的第一个Magento模型。在后面的章节中我们将讲解Magento的另外一种模型Entity Attribute Value Model。 在这章开始的时候,我撒了一个小谎。其实在Magento中,并不是所有的模型都继承自“Mage_Core_Model_Abstract”。在Magento最初的版本中,这个抽象类并不存在。所以有很多模型是直接继承自“Varien_Object”。不过这些并不影响我们创建Magento模型,了解一下就可以了,方便阅读Magento的代码。
分享到:
评论

相关推荐

    Magento-中文开发教程

    深入理解Magento-第四章 – 模型和ORM基础 深入理解Magento-第五章 – Magento资源配置 深入理解Magento-第六章 – 高级Magento模型 深入理解Magento-第七章 – 自定义Magento系统配置 深入理解Magento-第...

    Magento深入理解Magento

    ### Magento深入理解——强大配置系统解析 #### 一、引言 Magento是一款极其灵活且功能丰富的电子商务平台,其核心竞争力之一在于其强大的配置系统。这一系统不仅为开发者提供了极高的定制化能力,还确保了平台的...

    深入理解magento

    除了基础模型外,Magento还提供了一些高级模型概念,如集合(Collection)、EAV(实体-属性-值)模型和事件观察者模式。集合是多个模型对象的集合,常用于数据检索和遍历。EAV模型允许动态存储和管理商品属性,是...

    深入理解Magento.pdf

    【深入理解Magento——配置系统详解】 Magento是一款强大的开源电子商务平台,其配置系统是其核心组成部分,被誉为Magento的心脏。这个系统以XML的形式动态生成配置,掌控着模块、模型、类、模板等所有组件的行为。...

    深入理解magento_V1.0.pdf

    在深入理解 Magento V1.0 的过程中,我们会关注其配置系统和模块开发的基础知识。 首先,Magento 的配置系统是其心脏,它通过一套灵活的 XML 配置管理整个系统,包括 modules、models、classes、templates 等组件。...

    深入理解Magento详细培训教程

    总的来说,这个深入理解Magento的培训教程涵盖了从基础到进阶的所有关键知识点,旨在帮助初学者全面了解Magento的架构和工作方式。通过实际操作和理论学习相结合,你将能够熟练地进行Magento的开发工作,无论是构建...

    magento用户使用手册.pdf

    第一章:Magento介绍...................................................................................................................4 Magento 的特色.....................................................

    深入理解Magento-2.pdf

    本文档提供了创建和 Magento的应用程序进行安装定制的店面主题的说明。它描述 Magento的内容呈现过 程,并说明该系统的对有效地建立一个主题要求的范围内的观点层。该文件还走过日常前端开发人员的任务。

    深入学习Magento必读

    Magento是一款强大的开源电子商务平台,以其灵活的架构和丰富的功能特性深受...通过上述步骤,结合《深入理解Magento必读》文档,你将能够逐步掌握Magento的MVC架构,提升你的Magento开发能力,成为真正的Magento专家。

    Magento-中文开发教程.doc

    Magento是一款强大的开源电子商务平台,专为在线商家设计,提供丰富的功能和高度的可定制性。...通过学习这个教程,无论是初学者还是经验丰富的开发者,都能更深入地理解和运用Magento,打造功能强大的电子商务平台。

    深入理解Magento

    深入理解Magento,尤其是其配置系统,对于开发者来说至关重要。Magento的配置系统是其核心组件,它管理着系统中的模块、模型、类、模板等各个层面,通过XML来描述整个系统状态。这种配置方式虽然增加了编程的复杂性...

    megento中文学习文档

    8. **magento开发 -- 深入理解Magento第四章 – 布局,块和模板 .docx** 布局、块和模板是Magento视图层的关键组件,它们决定了用户界面的构造。这份文档将详细阐述布局XML文件、块类和模板文件的作用,以及如何...

    Magento模板制作教程1..doc

    ### Magento模板制作教程知识点解析 #### 一、Magento框架概览 Magento是一个广泛使用的电子商务平台,以其高度可扩展性和灵活...未来还可以进一步深入学习模型层和控制器层的相关知识,以全面掌握Magento的开发技巧。

    magento 中文开发手册

    4. **模型和 ORM 基础**:介绍了 Magento 如何使用 Entity-Attribute-Value (EAV) 模型存储数据,并展示了如何操作这些模型。 5. **资源配置**:说明了 Magento 中的数据资源管理和数据库操作。 6. **高级模型**:...

    Packtpub.Magento.1.3.PHP.Developers.Guide.Jan.2010.rar

    4. **模块开发**:深入讲解Magento的模块化设计,如何创建新的模块,编写控制器、模型、视图和数据存储,以及如何注册和启用新模块。 5. **支付与物流**:介绍Magento的支付和物流集成机制,包括如何添加新的支付...

    深入了解magento

    通过上述步骤,我们可以深入理解Magento配置系统的工作原理及其重要性。此外,通过创建简单的插件示例,不仅能够增强对Magento架构的理解,还能够在实践中提高编程技巧。总之,对于希望成为专业Magento开发者的...

    [Magento.开发书籍].Packt.Magento.1.3.PHP.Developer's.Guide.(2010)

    ##### 4. 高级主题 - **国际化支持**:对于跨国经营的企业来说,支持多语言是非常必要的。本书介绍了如何为Magento添加多语言支持。 - **支付与物流集成**:支付和物流是电商交易的重要环节。书中提供了关于如何集成...

    Magento Theme Design and Definitive.Guide.to.Magento

    2. **主题结构**:深入理解Magento的主题层次,包括默认、父主题和子主题的概念,以及它们之间的关系。 3. **CSS与模板文件**:学习如何修改和创建CSS样式表,以及如何调整布局XML文件以控制页面元素的展示。 4. *...

    magento-v1.7.0.2.国外官网原版

    在解压的"magento"文件夹中,你会找到构成Magento平台的各种组件,如`app`目录包含核心代码和模块,`skin`目录存储前端样式和图片,`var`目录用于缓存和日志,`lib`目录包含第三方库,以及`media`用于上传的产品图片...

Global site tag (gtag.js) - Google Analytics