学习实施基本ORM的提示/资源/模式

Bol*_*ock 11 php database model-view-controller orm

我已经看到了各种MVC框架以及PHP的独立ORM框架,以及其他ORM问题; 但是,大多数问题要求现有的框架开始使用,这不是我正在寻找的.(我也读过这个问题,但由于答案含糊不清,我不知道该怎么做.)

相反,我认为通过弄脏我的手并实际编写自己的ORM,即使是简单的ORM,我也会学得最好.除了我真的不知道如何开始,特别是因为我在其他ORM中看到的代码是如此复杂.

使用我的PHP 5.2.x(这很重要) MVC框架我有一个基本的自定义数据库抽象层,它具有:

  • 很简单的方法,如connect($host, $user, $pass, $base),query($sql, $binds)
  • 它支持的每个DBMS的子类
  • 表示SQL结果集的类(和各自的子类)

没有:

  • Active Record功能,我假设是一个ORM的东西(如果我错了,请纠正我)

编辑:澄清一下,我只有一个数据库抽象层.我还没有模型,但是当我实现它们时,我希望它们是原生的ORM模型(可以这么说),因此这个问题.

我已经阅读了一些关于ORM的内容,根据我的理解,它们通过将数据表示为基于PHP的类/对象,提供了从数据库本身进一步抽象数据模型的方法; 再次,纠正我,如果我错了或错过任何方式.

尽管如此,我还是喜欢其他任何使用ORM框架或多或少涉及过的人的简单提示.还有什么我需要注意的,简单的学术样本供我参考,或者我可以阅读的资源?

Max*_*Max 12

由于这个问题相当陈旧,我想你已经尝试过自己编写ORM了.尽管如此,正如我两年前写的一个自定义ORM,我仍然想分享我的经验和想法.

正如我所说,两年前我实施了一个定制的ORM,甚至在中小型项目中也取得了一些成功.我将它集成在一个相当流行的CMS中,当时(甚至现在)它缺乏这样的ORM功能.此外,在那时,像Doctrine这样的流行框架并没有真正说服我.自那时以来已经发生了很大的变化,并且学说2在一个可靠的框架中发展,所以,如果我现在可以选择实现我自己的ORM或者使用像Doctrine 2这样的流行框架之一进行生产使用,那么这将毫无疑问 - 使用现有的稳定解决方案.但是:实现这样一个框架(以简单的方式)是一个非常有价值的学习练习,它帮助我在使用更大的开源ORM方面做了很多工作,因为您可以更好地理解与对象关系映射相关的陷阱和困难.

实现基本的ORM功能并不困难,但只要对象之间的关系映射发挥作用,就会变得更加困难/有趣.


我是如何开始的?

让我着迷的是Martin Fowlers的书籍企业应用程序架构模式.如果您想编写自己的ORM,或者即使您只是使用某个ORM框架,请购买此书.它是涵盖对象关系映射领域的许多基本和高级技术的最有价值的资源之一.阅读它,你会得到很多关于ORM背后模式的好主意.

基础架构

我决定是否要使用Active Record方法或某种Data Mapper.此决定影响数据库中的数据如何映射到实体.我决定实现一个简单的Data Mapper,与Doctrine 2或Java中使用的Hibernate相同.Active Record是Zend Framework中 ORM功能的方法(如果可以的话).Active Record比Data Mapper简单得多,但也更加有限.阅读这些模式并检查上述框架,您可以非常快速地获得差异.如果您决定使用Data Mapper,您还应该阅读PHPs反射API.

查询

我有宏伟的目标,以创建自己的查询语言,就像DQL在教义或HQL Hibernate中.我很快abondoned,作为编写自定义的SQL语法/词法分析器似乎办法复杂(这真的是!).我所做的就是实现一个查询对象,以封装哪个表查询中涉及的(这就是重要的,因为你需要从数据库中的数据映射到相关类为每个表)中的信息.

查询我的ORM中的对象看起来像这样:

public function findCountryByUid($countryUid) {
    $queryObject = new QueryObject();
    $queryObject->addSelectFields(new SelectFields('countries', '*'))
            ->addTable(new Table('countries'))
            ->addWhere('countries.uid = "' . intval($countryUid) . '"');

    $res = $this->findByQuery($queryObject);
    return $res->getSingleResult();
}
Run Code Online (Sandbox Code Playgroud)

组态

通常,您还需要具有某种配置格式,Hibernate使用XML(以及其他),Doctrine 2使用PHP注释,EZComponents在其Persistent Object组件中使用PHP数组作为配置格式.这也是我使用的,它似乎是一个自然的选择,我使用的CMS也使用PHP配置格式.

使用该配置,您可以定义

  • 哪个表被映射到哪个类
  • 哪些字段应该映射到类实例
  • 表的字段有什么类型(int,string等)
  • 实体之间的关系(例如,User类具有对UserGroup类的引用)
  • 等等

这就是您在Data Mapper中使用的信息,用于将DB结果映射到对象.

履行

由于编写自定义ORM的复杂性,我决定采用强大的测试驱动方法.TDD与否,编写许多单元测试对于这样的项目来说是一个非常好的主意.除此之外:亲自动手,让Fowlers的书保持密切.;-)


正如我说,这是真的值得去努力,但我也不会转回去想再做一次,因为存在时下成熟的框架了.

我不使用我的ORM了,它的工作,但缺乏许多功能,其中包括:延迟加载,组件映射,事务支持,缓存,自定义类型,预处理语句/参数等,并it's性能wasn't不够好在大型项目中使用它.

尽管如此,我希望我可以给你一些出发点在ORM的领域,如果你didn't认识他们了.;-)