您对Doctrine ORM的体验如何?

paa*_*aan 26 php orm doctrine doctrine-orm

你对学说的体验是什么?我从来都不是一个ORM类型的人,我主要管理像adodb这样的基本数据库抽象层.

但我理解了它的所有概念和好处.所以当一个需要ORM的项目出现时,我认为我会尝试一个ORM框架.

我要在学说和推进之间做出决定,所以我选择了学说,因为我不想处理这个要求.

我不知道我做错了什么.我带着正确的心态进来了.我绝不是一个'初级'php小子.但是我每一步都在与系统作斗争.有很多文档,但都觉得有点混乱.而简单的东西,如YAML到数据库表创建只是不工作,只是没有错误或任何东西bork out.很多其他的东西工作有点时髦需要在工作之前进行额外的调整.

也许我在这里做了一些愚蠢的新手假设,一旦我发现它是什么我会有一个啊哈的时刻.但现在我完全讨厌这个系统.

是否有人可以给出一些提示或者可能指向我关于这个主题或某个权威网站/人的关于此的良好资源?或者只是推荐另一个"正常工作"的ORM框架?

Mic*_*ham 42

我的感情很复杂.我只是SQL的高手,因为它很容易验证.您可以快速测试SELECT语句,直到获得正确的结果.并且重构是一件轻而易举的事.

在Doctorine或任何ORM中,有如此多的抽象层,它几乎就像强迫症(强迫症/强迫症).在我最近的项目中,我尝试了Doctrine,我打了几个墙.我花了几天时间才找到一个解决方案,我知道我可以在几分钟内用SQL编写.那太令人沮丧了.

我脾气暴躁.SQL的社区是巨大的.社区/对学说的支持是微不足道的.当然你可以查看源代码并尝试弄明白......这些问题需要花费数天的时间才能弄明白.

一句话:不要尝试使用Doctrine或任何ORM,而不需要花很多时间自己进行grokking.


luc*_*303 10

我认为mtbikemike完美地总结道:"我花了几天的时间才找到一个解决方案,我知道我可以在几分钟内用SQL编写." 那也是我的经历.SAD(慢速应用程序开发)得到保证.更不用说每个角落都有丑陋的代码和限制.需要几分钟的事情需要几天时间,通常情况会更复杂,花费数小时或数天的事情是不可行的(或者不值得花时间).由此产生的代码更加冗长和含糊不清(因为我们确实需要另一种查询语言DQL,以使事情更具可读性).奇怪的虫子四处都是,大部分时间都花在追捕它们并遇到限制和问题.学说(我只使用v2.x)类似于徒劳无功,完全没有任何好处.它是我目前系统中最讨厌的组件,也是唯一一个存在巨大问题的组件.进入一个新的系统,我总是来自db到实体类,试图找出代码中不同位置的哪个名称是正确的.一场噩梦.

我没有看到一个专业的学说,只有缺点.我不知道为什么它存在,我希望它每天都没有(至少在我的项目中).


小智 9

我们已经使用Propel和Symfony一起使用了2年,并且使用Symfony的Doctrine超过1年.我可以说,使用MVC框架迁移到ORM是我们所做的最好的一步.我建议坚持使用Doctrine,尽管学习如何使用它需要一些时间.最后,您会发现您的代码更具可读性和灵活性.

如果你正在寻找一个从哪里开始,我会推荐Symfony Jobeet教程http://www.symfony-project.org/jobeet/1_4/Doctrine/en/(第3章,第6章涵盖基础知识),当然学说文档.

正如我上面所写,我们已经使用Doctrine一段时间了.为了使我们的工作更加舒适,我们开发了一个名为ORM Designer(www.orm-designer.com)的工具,您可以在图形用户界面中定义数据库模型(不再有YAML文件:-),这些文件根本不是很糟糕).你也可以找到一些有用的教程.

  • 这似乎是推销员的回答."是的,使用doctrine2,然后使用我们自己的ORM设计师",是的,没有任何偏见. (4认同)

Ror*_*ory 6

我的经历听起来与你的相似.我刚开始使用学说,从未使用过Propel.但是我对学说非常失望.它的文档很糟糕.组织不良,而且相当不完整.


小智 6

Propel和Doctrine使用PDO.PDO在Oracle数据库中存在许多漏洞.所有这些都与CLOB字段有关.如果您正在使用Oracle,请在开始新项目之前牢记这一点.这些漏洞几年前就开放了.Doctrine和PDO将与Oracle和CLOB一起崩溃


小智 5

我在一个中型项目中使用 Doctrine,在该项目中我必须使用我不拥有的预先存在的数据库。它为您提供了许多内置功能,但我有一个主要的抱怨。

由于我必须从数据库生成我的模型而不是反之亦然,我的模型离数据库太近了:字段的名称与数据库列的名称非常相似,要获取必须在基本 sql 中查询的对象(其中我应该放那个代码,我如何测试它?)等。

最后,我不得不为学说编写一个复杂的包装器,这让我质疑是否只使用旧的 dao/model 方法并将教义排除在外是否会更容易。陪审团仍在讨论中。祝你好运!


Den*_*nis 5

2015 年使用 Doctrine 2.5。看起来进展顺利。直到我想使用两个实体(在 JOIN 中)。[在我掌握了 DQL 之后现在好多了]

好的:

  • 为我生成 SQL
  • 外键的使用和参照完整性
  • 默认生成 InnoDB
  • 使用学说命令行工具对 SQL 进行的更新

好的:

  • 高度了解命名和映射以及如何命名以及如何将实体映射到实际表

坏的

  • 需要很多时间 - 学习查询构建器的自定义 API。或者弄清楚如何做一个简单的 JOIN,想知道是否有更好的技术。如果你想进行面向对象的查询,简单的 JOIN 似乎需要编写自定义函数。
  • [第一印象更新] -- 我选择使用 DQL,因为它与 SQL 最相似

在我看来,该工具在概念上很棒,但其正确执行需要开发人员花费大量时间来上手。我很想将它用于实体 SQL 生成,但随后将 PDO 用于实际输入/输出。只是因为我还没有学习如何使用 SQL 进行外键和引用完整性。但是学习这些似乎比学习 Doctrine 的来龙去脉要容易得多,即使使用简单的东西,比如相当于 JOIN 的实体。

现有项目中的原则

我(刚刚开始)使用 Doctrine 在现有项目上开发新功能。因此,我没有为该功能添加新的 mysql 表,而是添加了实体(它使用 Doctrine 模式生成为我创建了表)。我保留不将 Doctrine 用于现有表,直到我更好地了解它。

如果我要在现有表上使用它,我会首先......清理表,其中包括:

  • 添加作为主键/代理键的 id 列
  • 使用 InnoDb/事务能力表
  • 将其适当地映射到实体
  • 运行 Doctrine 验证工具 ( doctrine orm:validate-schema)

这是因为 Doctrine 对您的表做出了某些假设。并且因为您本质上将通过代码来驱动您的表。因此,您的代码和表格必须尽可能达到 1:1 的一致性。因此,Doctrine 通常不适用于任何“自由格式”表格。

但是,您可能会谨慎一些,并且在某些情况下,可以避免一些小事情,例如您的实体中没有考虑的额外列(我认为 Doctrine 不会检查,除非您要求)。您将不得不构建您的查询,知道您正在逃避什么。即,当您请求一个“实体”作为一个整体时,Doctrine 会专门通过列名请求实体的所有字段。如果您的实际模式包含更多列名,我认为 Doctrine 不会介意(它不会,因为我已经通过在我的模式中创建一个额外的列进行了验证)。

所以是的,可以使用 Doctrine,但我会从小处开始,小心翼翼。首先,您很可能必须转换您的表以支持事务并拥有代理索引(主键)。对于诸如外键和参照完整性之类的东西,您必须使用 Doctrine 来完善您的实体并将它们完美匹配。您可能必须让 Doctrine 重新构建您的架构以使用它自己的索引名称,以便它可以正确使用 FK 和 RI。您实际上是在放弃对表的一些控制权给 Doctrine,因此我相信它必须以自己的方式了解架构(例如能够使用自己的索引名称等)。


Pet*_*sko 5

派对有点晚了,但让我把我的两分钱扔在这里。我将与Laravel建立联系,因为这是我使用的框架。

Active Record vs. 数据映射 vs. 正确的 OOP

Laravel 和许多其他框架都喜欢Active Record。它可能非常适合简单的应用程序,并且可以节省您进行琐碎的数据库管理的时间。然而,从 OOP 的角度来看,它是一种纯粹的反模式SoC(关注点分离)刚刚被杀死。它在模型属性和 SQL 列名称之间创建耦合。对于扩展和未来的更新来说很糟糕。

随着您的项目增长(是的,它会!),ActiveRecord 会越来越痛苦。甚至不要考虑轻松更新 SQL 结构。请记住,您的 PHP 代码中到处都是列名。

我被聘为一个项目,该项目的目标是在未来变得相当大。我看到了 ActiveRecord 的局限性。我坐了 3 周,并使用 Data Mapper 重写了所有内容,它将 DB 与上面的层分开。

现在,回到Data Mapper以及为什么我没有选择 Doctrine

Data Mapper的主要思想是,它将您的数据库与您的代码分开。从 OOP 的角度来看,这是正确的方法。SoC规则!我详细回顾了Doctrine,我立即不喜欢几个方面。

  • 映射。为什么世界上会有人使用注释作为命令?我认为这是一种非常糟糕的做法。为什么不直接使用 PHP 类来存储映射关系?
  • 地图的 Yaml 或 XML。再次,为什么?当可以使用常规 PHP 类时,为什么要浪费时间解析文本文件。另外,一个类可以被扩展、继承,可以包含方法,而不仅仅是数据。等等。
  • 如果我们有一个映射器和一个携带数据的模型,那么它应该是存储模型的映射器。诸如$product->save()ar 之类的方法并不好。模型处理数据,它不应该关心向数据库存储任何内容。这是一个非常紧密的耦合。如果我们花时间构建一个映射器,那为什么不用$mapper->save($product). 根据定义,映射器应该知道如何保存数据。

毫无疑问,Doctrine 或 Eloquent 之类的工具可以在开始时节省时间。但这是每个人都面临的棘手问题。/开发时间/未来更新/价格/简单性/遵循OOP原则/之间的正确折衷是什么?最后,由您来回答和正确决定。

我自己的 DataMapper 而不是 Doctrine

我最终开发了自己的 DataMapper,并且已经将它用于我的几个小项目。它工作得非常好,易于扩展和重用。大多数时候我们只是设置参数,不需要新代码。

以下是关键原则:

  • 模型携带数据,类似于 Laravel 的模型。$model以下示例的示例变量。
  • ModelMap包含一个字段,该字段将模型的属性映射到 SQL 数据库中表的列。ModelMaps 知道表名、id 等。它知道哪些属性应该转换为json,哪些属性应该隐藏(例如deleted_at)。此 ModelMap 包含具有相同名称的列(连接表)的别名。示例变量:$modelMap.
  • ModelDataMapper是一个在控制器中接受ModelModelMap并提供 store/getById/deleteById 功能的类。您只需拨打电话$modelMapper->store($model),仅此而已。
  • 基础 DataMapper 还处理分页、搜索能力、将数组转换为 json、添加时间戳、检查软删除等。对于简单的用法,基础 DataMapper 就足够了。对于任何更复杂的事情,使用继承来扩展它是很容易的。

  • 我喜欢你从抽象角度的详细回应,而不是抱怨一个用例。您愿意分享您的自定义数据映射器吗?我在 Doctrine 上投入了大量资金,但我喜欢寻找替代方案,而且您的解决方案听起来很有趣。 (2认同)

YiS*_*iSh 3

我不是 Doctrine 方面的专家 - 我自己刚刚开始使用它,我不得不承认它的体验有点复杂。它为您做了很多事情,但如何告诉它这样做或那样做并不总是立即显而易见的。

例如,当尝试使用 YAML 文件进行自动关系发现时,多对多关系无法正确转换为 php 模型定义。正如您提到的,没有错误,因为它根本没有将其视为多对多。

我想说,您可能需要时间来了解这种或那种做事方式以及元素如何相互作用。有时间一步一步地做事情是一件好事,并且一次一个地以一种孤立的方式处理问题。尝试一次做太多事情可能会让人不知所措,并且可能会更难真正找到问题所在。