Sexy ORM — 全面革新的 ORM 系统
前言:
QeePHP 提供了一个全功能的 ORM 系统,能够完善处理各种对象间的复杂关系,为开发者采用面向对象设计来解决业务问题提供了有力的支持。不过实践中,我们也发现 QeePHP 现有的 ORM 系统存在各种不足。因此,全面革新 ORM 系统成为了一项重要的任务。该任务名为:Sexy ORM。
Sexy ORM 是 QeePHP 下一个版本的重点之一,目标是为 QeePHP 提供一个更容易理解和使用的 ORM 架构。
在 QeePHP 现有 ORM 架构的基础之上,Sexy ORM 更符合面向对象开发的思想,并且为团队协作和高效开发提供了更多的支持。
清晰的模型定义
QeePHP 目前使用的 ORM 中,模型的属性、关联等是在模型类的 __define() 静态方法中定义的。
这种定义方式不够直观,而且还有下列弊端:
- 违背了面向对象设计的初衷,强迫开发者回到以数据库为中心的设计方式;
- 模型代码中的属性定义不完整,如果不查看数据表无法知道模型到底有哪些属性;
- 当模型或数据表改变时,很可能出现模型与数据表不一致的情况;
- 无法通过反射等机制完成模型的自动化维护,给团队协作带来了困难。
在 Sexy ORM 中,将采用更清晰的模型定义方式:
< ?php
/**
* 作者
*
* @table authors
*/
class Author extends QModel
{
/**
* ID
*
* @var int
* @pk
*/
public $id;
/**
* 名
*
* @var string
* @size 60
*/
public $first_name;
/**
* 姓
*
* @var string
* @size 60
*/
public $last_name;
/**
* 电子邮件
*
* @var string
* @optional
* @size 80
*
* @validate_is_email '必须是有效的电子邮件地址'
*/
public $email;
/**
* 该作者参与撰写的书籍
*
* @var coll of Book
* @has_many :through writings # 通过 writing 属性关联到书籍
*/
public $books;
/**
* 该作者的写作记录
*
* @var coll of Writing
* @has_many :cascade destroy # 删除作者时,删除作者的撰写记录
* :order 'finished_date DESC' # 按照撰写完成时间排序
* :limit 5 # 默认只读取作者最近 5 个撰写记录
*/
public $writings;
/**
* 全名
*
* @var string
* @getter get_full_name
*/
public $full_name;
/**
* 返回作者的全名
*
* @return string
*/
function get_full_name()
{
return $this->first_name . ', ' . $this->last_name;
}
.... 其他领域逻辑方法 ....
}
新的定义方式将模型的所有属性都直接写了出来,而且模型间的关联也通过属性来直接定义。
定义属性时,每一个属性的特性都使用注解(@ 开头的注释文字)来描述。示例中用 @var 指定了属性的类型,@size 则指定了属性值的最大长度。除了属性,模型类的特性也使用注解来描述,例如 @table 指定了存储该模型的数据表名称。
新的模型定义具有下列特点:
- 属性由对象成员变量直接定义;
- 基于注解的属性描述;
- 基于注解的类定义描述。
由于采用了与现在完全不同的模型定义方式,因此在 Sexy ORM 中,模型不再是从数据表创建,而是由开发人员来创建。创建好的模型以最自然的方式来勾勒出模型的概貌,并且通过注解明确模型的方方面面。
新模型定义带来的好处
新的模型定义方式,带来了一些显著的好处:
- 模型的定义完全以面向对象为出发点,在设计阶段排除了数据库;
- 所有的属性通过阅读源代码即获知,实现设计上的“所见即所得”;
- 模型的变化可以自动映射到数据表之上,配合数据库迁移脚本,可以消除模型与数据库不一致的情况;
- 基于注解的描述,允许我们使用自动化工具完成模型的维护工作;
- 模型的属性与关联定义更直观,易于阅读和理解。
而且新的模型定义方式可以让 IDE 自动提示对象属性,进一步提高了开发效率:

新的模型创建流程
目前,我们的创建一个模型的流程是:做初步设计、建立数据表、从数据表生成模型文件。
这种流程最大的问题就在于设计数据表变成了设计模型的一部分,而模型原本应该是完全从面向对象角度来思考的,不适宜过早和数据表发生关系。
改善后的模型创建流程是:
- 设计时,以模型为关注焦点;
- 创建模型的类文件;
- 自动从模型定义生成数据库迁移脚本;
- 通过数据库迁移脚本来创建数据表。
这里提到的数据库迁移脚本是一种自动化工具,具备下列功能:
- 分析模型类,确定模型的所有属性及属性类型等信息;
- 生成创建数据表的脚本代码;
- 当模型发生变化后,可以自动比对模型与数据表的结构,并生成更新数据表的脚本代码。
由于数据库迁移脚本的引入,团队协作时,模型的维护工作得到了显著简化。更新模型后,将会自动提供开发者模型与数据库出现了不匹配情况。此时开发者可以通过自动化工具生成一个新的数据库迁移脚本。
由于团队成员之间利用 Subversion 等源代码版本控制系统进行代码的更新,因此一个开发者对模型修改后产生的源文件和数据库迁移脚本都能够同步到其他团队成员那里。最终,只需要执行数据库迁移脚本,模型更新的同步工作即可轻松完成。
基于 PHP 5.3
Sexy ORM 是为 PHP 5.3 及更新版本 PHP 所设计的,充分利用了新版本 PHP 的功能。这些新功能包括延迟静态绑定、静态魔法调用、名字空间等。这些新功能的应用,让我们的模型类变得更整洁,而且使用时具备更佳的灵活性。
Sexy ORM 相对于 QeePHP 现有 ORM 的新特征:
- 基于 PHP 5.3;
- 所见即所得风格的模型定义;
- 全面的自动化工具;
- 更完善的查询支持;
- 更多的动态查找方法;
- 更好的关联处理;
- 更简洁的模型类定义;
- 更好的 IDE 支持;
- 完善的反射支持;
- 性能改进。
虽然 Sexy ORM 的许多新特征依赖于 PHP 5.3 版本,但由于在基础架构和实现上和现有 ORM 的传承,Sexy ORM 的一些特性也将陆续出现在 QeePHP 现有的 ORM 系统中。这些即将出现的新特征包括:
- 数据库迁移脚本支持;
- 更完善的查询支持;
- 更好的关联处理;
- 性能改进。
路线图
虽然 PHP 5.3 近期已经发布了 RC1 版本。但根据以往的经验,PHP 每一次重大升级的版本都需要两个较小版本的更新后才能稳定下来,因此 PHP 5.3.2 或更新的版本将会步入成熟期。
我们预计在 2010 年上半年,PHP 5.3 系列会开始普及,此时也将是 Sexy ORM 正式推出的时机。

湿太可别为了面向对像而面向对象哇,哈.
以后出干净版的代码还得注意:模型的注释要留哇,哈.
我觉得,数据库中的字段就是自然的属生,自己附加的qee2.1那种挺好哇.
楼上提到“以后出干净版的代码还得注意:模型的注释要留哇,哈.”,这个是完全可以解决的。因为在部署模式下,每一个模型解析的结果都会缓存起来。把这份缓存文件以及包含在干净版代码中即可。
用的反射?
中元提到这个问题挺重要的..
额 ..我还是喜欢rails那种定义方式..
这个让我想到贫血模型实体类..
当然是使用反射了。这个例子只是没有提供方法而已。有了方法就是充血模型了。
貌似这个并没有办法解决
修改了数据库要重新生成model的时候 原有业务方法的保留问题.
之前有提到要用yaml另行外部定义 我觉得这条路子比较适合,也比较容易做migration
其实新设计要解决的一个大问题就是数据库设计。
改进后的设计是从模型生成 migration,再从 migration 生成 db table。
和你理解的正好相反。这篇文章我继续写完,大家就明白了。
这才是完美方案嘛。哈哈哈哈!
等到有一天,用绘图工具就能生成模型、数据表代码的时候,那就真的Sexy了!哈哈!
WebSetup 肯定会提供建立模型的功能,直接填写表单,设置好模型的主要属性和基本设置。然后自动生成模型、migration、form 等一系列文件。
永远的支持~
打酱油路过。
可以参考下Criteria的做法。symfony中使用的,个人觉得很好用,特别是对表进行改动的时候,原有的代码兼容性非常好。