Symfony2Book04:Doctrine01-介绍模型(Model)-阿里云开发者社区

开发者社区> 技术小阿哥> 正文

Symfony2Book04:Doctrine01-介绍模型(Model)

简介:
+关注继续查看

如果你想学习模型和超级模型的最新技术,本章将无法对你有所帮助。但如果你仅仅只是想学习一个模型,你应用程序中元数据的层,那么请阅读本章内容。本章所描述的模型用于构建MVC应用程序。

MVC(模型-视图-控制)最初由Trygve Reenskaug在Smalltalk平台上提出的应用程序设计模式。MVC的主要思路就是将展示从数据中分离出来,把控制器从展示中分离出来。这种分离让应用程序的各个部分都只关注一个目标。控制器关注模型数据的改变,模型将其数据向视图开放,而视图则关注创建模型的展示(如HTML页面展示博客博文)。

举个例子,当用户访问你博客首页时,用户的浏览器发送一个请求,该请求被发给控制器要求渲染博文列表。控制器计算要显示的博文列表,从数据库检索Post模型,并将Post数组发送给视图,视图渲染HTML以便在浏览器中显示。

到底什么是模型

模型在MVC中用M表示。它是MVC应用程序中三大部件之一。模型负责根据来自控制器的请求改变其内部状态,并将其当前状态信息传递给视图。它是应用程序主逻辑容器。

举个例子,如果你正在构建一个博客,那么你将拥有一个Post模型。如果你正在构建一个内容管理系统,那么你需要一个Page模型。


  1. <?php 
  2.  
  3. namespace Blog; 
  4.  
  5. class Post 
  6.     private $title
  7.     private $body
  8.     private $createdAt
  9.     private $updatedAt
  10.  
  11.     public function __construct($title$body
  12.     { 
  13.         $this->title     = $title
  14.         $this->body      = $body
  15.         $this->createdAt = new \DateTime(); 
  16.     } 
  17.  
  18.     public function setTitle($title
  19.     { 
  20.         $this->title     = $title
  21.         $this->updatedAt = new \DateTime(); 
  22.     } 
  23.  
  24.     public function setBody($body
  25.     { 
  26.         $this->body      = $body
  27.         $this->updatedAt = new \DateTime(); 
  28.     } 
  29.  
  30.     public function getTitle() 
  31.     { 
  32.         return $this->title; 
  33.     } 
  34.  
  35.     public function getBody() 
  36.     { 
  37.         return $this->body; 
  38.     } 
  39. }

很明显,上述类非常简单也易于测试,除了一个简单的博客引擎外它几乎完成了一切。

就是这样,现在你知道在Symfony2中模型是什么:它是你想将其保存在某种顺序数据存储机制中并随后可以检索的类。本章节的其它部分将专门讲述它是怎么与数据库交互的。

数据库和Symfony2

Symfony2自己并没有实现ORM(对象关系映射)或DBAL(数据库抽象层),Symfony2要解决它并没有什么问题,但这没有任何意义。Symfony2提供了与类似Doctrine或Propel这样库的深度集成,这些库提供了ORM和DBAL包,可以让你使用你最喜欢的库。

ORM是对象关系映射的缩写,它代表一种在不兼容类型系统之间转换数据的编程技术。我们有一个Post,它被做为一条记录被保存在数据库里,但在应用程序中它又要做为Post类的一个实例来展现。将数据库的数据表转换成对象称之为对象关系映射。我们将发现这个术语有点过时,因为它只能在处理关系性数据库时使用。现在存在着大量的非关系性数据存储机制,有一种面向文档的数据库(如MongoDB),它所使用的术语是ODM(对象文档映射)。

接下来,你将学习关于Doctrine2 ORM和Doctrine2 ModgoDB ODM(为当下流行的文档存储:MongoDB所提供的ODM服务),这两者与Symfony2有着最深层次的集成。

模型不是数据表

模型类感觉就象是数据库的数据表,每个对象实例表示单个记录,这样的概念随着Ruby on Rails框架和Active Record设计模式的流行而广为人知。在应用程序模型层设计之初这样考虑是很好的,特别是在你正为修改模型数据而提供简单的CRUD(增删改查)时。

但这种想法其实会引起一个问题,一旦你完成应用程序的增删改查而要去添加更多的业务逻辑时,上述想法会引发 下面的限制:

  1. 在软件实际使用前先设计一个模式,就好象在知道你要埋什么之前先挖个坑。可能你埋的东西正好适合你所挖的洞,但如果你要埋辆大型的消防车呢?要想有效工作的话,你需要完全不同的思路;
  2. 数据库针对性地去适应你应用程序的需要,而不是反过来;
  3. 有些数据存储引擎(如文档数据库)并没有数据表、记录甚至是模式的概念,如果你认为模型就是数据表的话,你将很难使用它;
  4. 在你设计应用程序域的时候脑海中浮现的却是数据库模式,那么接下来在两者之间的最小公约数原则会让你焦头烂额的。

想象一起,脑子里想着数据库的结构,然后集中注意力去编写干净的模型以满足你业务需求是多么地痛苦,好在Doctrine2 ORM已经解决了这个问题。在要求你去考虑如何持久化数据之前,它会先让你设计你的类和相关的交互。

范式转换

随着Doctrine2的介绍,一些核心范式被转换。领域驱动设计(DDD)告诉我们对象是对真实世界原型建模的最好模型。例如Car对象是最好地建模,它包含Engine、4个Tire实例等,并且应该被CarFactory(知道如何将部件组装起来)生产出来。领域驱动设计本身就可以写一本书,因为它相当广泛。然而,考虑到本章的目的,我们需要知道的是汽车自己是无法启动的,它需要一个外部作用来启动它。与此相似,模型没有外部作用也是无法保存自己的,因此下面这段代码违反了DDD,并为重新设计一个干净、易测代码带来麻烦 。


  1. $post->save();

Doctrine2并不是传统的Active Record的实现。Doctrine2使用一个不同的模式集,几乎完全实现了Data Mapper和 Unit Of Work模式,下面是如何使用Doctrine2来保存实体的示例:


  1. $manager = //... 得到对象管理器实例 
  2.  
  3. $manager->persist($post); 
  4. $manager->flush(); 

“对象管理器”是Doctrine提供的核心对象,它的作用是持久化对象。你不久将学到这个对象的更多内容。这个范式转换让我们摆脱了所有的基类(如Post不需要继承基类)和静态依赖。任何对象都可以保存到数据库并随后进行检索。更有甚者,一旦被持久化,该对象就可以通过对象管理器进行管理,直到管理器明确进行清理。这意味着所有对象的交互都发生在内存,直到调用$manager->flush()方法才发往数据库。不用说与大多数其它对象持久化模式相比,这个机制提供了一个即时数据库和优化查询,因为持久化尽可能地“懒”(它们的执行总是延迟到最后一刻)。

Active Record模式最重要的方面就是性能,或者说,构建一个高性能的系统是困难的。通过使用事务和内存对象改变跟踪,Doctrine2最大限度地减少与数据库的通信,从而节省数据库执行时间和昂贵的网络通信。

结论

感谢Doctrine2,使得Symfony2的模型现在也许已经是最简单的概念:它置于你的完全控制之下,而且不会受到持久化细节的限制。

通过与Doctrine2联合,你可以对你在持久化细节方面的代码感到放心,Symfony2使构建数据库方面的应用程序变得十分简单。应用程序代码保持干净,这将缩短开发时间并提高代码的可读性。



本文转自 firehare 51CTO博客,原文链接:http://blog.51cto.com/firehare/585426,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
什么是 SAP 电商云 Spartacus UI 的 proxy facade
什么是 SAP 电商云 Spartacus UI 的 proxy facade
4 0
使用 Angular Transfer State 的一个具体例子
使用 Angular Transfer State 的一个具体例子
4 0
SAP Commerce Cloud SmartEdit 学习笔记
SAP Commerce Cloud SmartEdit 学习笔记
6 0
使用脚本进行 SAP Spartacus 安装工作
使用脚本进行 SAP Spartacus 安装工作
6 0
SAP 电商云 Spartacus UI 支持延迟加载的新功能的入口设计
SAP 电商云 Spartacus UI 支持延迟加载的新功能的入口设计
5 0
Redis | Redis基础类型常用操作命令
Redis | Redis基础类型常用操作命令
6 0
SAP 电商云 UI State persistence 状态持久化设计的入口 - initSync
SAP 电商云 UI State persistence 状态持久化设计的入口 - initSync
6 0
Angular Public API 接口设计
Angular Public API 接口设计
4 0
关于 SAP Spartacus feature library 里的 _index.scss 文件
关于 SAP Spartacus feature library 里的 _index.scss 文件
4 0
从一个实际的例子触发,理解什么是 Rxjs 的 defer 函数
从一个实际的例子触发,理解什么是 Rxjs 的 defer 函数
5 0
9455
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载