gpt4 book ai didi

php - 学习实现基本 ORM 的技巧/资源/模式

转载 作者:可可西里 更新时间:2023-10-31 22:12:13 25 4
gpt4 key购买 nike

关闭。这个问题需要更多focused .它目前不接受答案。












想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .

7年前关闭。



Improve this question




我在这里看到了各种 MVC 框架以及用于 PHP 的独立 ORM 框架,以及其他 ORM 问题;然而,大多数问题都要求从现有框架开始,这不是我想要的。 (我也读过 this SO question ,但我不知道该怎么做,因为答案含糊不清。)

相反,我认为通过亲自动手并实际编写自己的 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 框架的其他人那里得到一些简单的提示。还有什么我需要注意的,简单的,学术样本供我引用,或者我可以阅读的资源?

    最佳答案

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

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

    实现基本的 ORM 功能并不太难,但是一旦对象之间的关系映射发挥作用,它就会变得更加困难/有趣。

    我是如何开始的?

    让我着迷的是 Martin Fowlers 的书 Patterns of Enterprise Application Architecture .如果您想编写自己的 ORM,或者即使您只是在使用某个 ORM 框架,请购买这本书。它是最有值(value)的资源之一,涵盖了与对象关系映射领域有关的许多基本和高级技术。阅读它,你会得到很多关于 ORM 背后模式的好主意。

    基础架构

    我决定是否要使用 Active Record方法或某种 Data Mapper .此决定会影响数据库中的数据如何映射到实体。我决定实现一个简单的数据映射器,方法与 Doctrine 2 相同。或 Hibernate在 Java 中使用。 Active Record 是 Zend Framework 中 ORM 功能的方法(如果您可以这样称呼的话) . Active Record 比 Data Mapper 简单得多,但也受到更多限制。阅读这些模式并检查提到的框架,您会很快发现差异。如果您决定使用数据映射器,您还应该阅读 PHPs reflection API .

    查询

    我有一个雄心勃勃的目标,即创建自己的查询语言,就像 DQL 一样。在教义或 HQL在休眠中。我很快就放弃了,因为编写自定义 SQL 解析器/词法分析器似乎很复杂(而且确实如此!)。我所做的是实现一个 Query Object ,为了封装查询中涉及哪个表的信息(这很重要,因为您需要将数据从数据库映射到每个表的相关类)。

    在我的 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();
    }

    配置

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

    使用该配置,您可以定义
  • 哪个表映射到哪个类
  • 哪些字段应该映射到类实例
  • 表的字段有什么类型(整数、字符串等)
  • 实体之间的关系(例如 User 类引用了 UserGroup 类)

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

    实现

    由于编写自定义 ORM 的复杂性,我决定采用强大的测试驱动方法。无论是否使用 TDD,编写许多单元测试对于这样的项目来说都是一个非常好的主意。除此之外:弄脏你的手,让福勒的书靠近。 ;-)

    正如我所说,这确实值得付出努力,但我不想再做一次,这主要是因为当今存在的成熟框架。

    我不再使用我的 ORM,它可以工作,但缺少许多功能,其中包括:延迟加载、组件映射、事务支持、缓存、自定义类型、准备好的语句/参数等。而且它的性能不够好用于大型项目。

    尽管如此,我希望我能给你一些 ORM 领域的起点,如果你还不知道的话。 ;-)

    关于php - 学习实现基本 ORM 的技巧/资源/模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2887530/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com