15

背景

我正在使用 Symfony 2 开发一个应用程序,该应用程序的结构使得“核心”包定义实体、关系和字段。然后,其他捆绑包能够通过继承专门化核心功能,即所谓的“子”捆绑包。

Doctrine 2 注释已用于定义称为“包”的核心实体。一个“包”将建筑设计和一块土地联系在一起——本质上是一个房屋和土地包。我已将示例简化为更基本的形式,因此您不会在下面的示例中找到 Land 和 ChildLand 的定义,但您可以假设它们已经以类似的方式实现。

更新

根据 FreeNode 的#symfony 频道上的用户的说法,这是一个原则问题,因为 app/console 命令只是调用了原则控制台。我正在使用学说 2.3。

这是一个图表,显示了导致问题的一般情况,应该有助于可视化场景:

imgur 链接到全尺寸图片类型提示违约

此外,这里是关于教义问题跟踪器的错误报告的链接:http: //www.doctrine-project.org/jira/browse/DDC-2605

更新 2 - 更详细的 ERD

实体之间的关系结构受到质疑,因此下面是我们正在实现的数据结构的更好示例。

主要要求再次是拥有提供一组共享实体和字段的核心类。公司捆绑包中的子类扩展了这些核心类。

我们确实详细考虑过 EAV,但在这种方法中,我们将花费更多时间来创建一个平台和工具来管理 EAV 数据,而不是满足当前的业务需求,我们将无法使用原则来管理实体,因为它们将在数据库等中定义。

随着时间的推移,我更好地理解了这个问题,似乎唯一的问题是由教义的 CLI 工具生成的 getter 和 setter,因为它们破坏了下面提到的类型提示合同。当手动纠正这些问题时,此结构可以完美运行。

imgur 链接到全尺寸图片详细的数据结构

使用 CLI 工具生成实体

所以,最初我使用命令行工具...

> app/console doctrine:generate:entity

...生成具有基本字段映射的实体存根,然后手动将关系添加到土地(因为该工具似乎不支持关系):

这是生成的代码:

核心包实体: http: //pastebin.com/3ujPT1mJ

子包实体: http: //pastebin.com/sjAB0XJ2

生成 Getter 和 Setter

接下来,我通过执行以下命令生成 getter 和 setter:

> app/console doctrine:generate:entities CompanyCoreBundle

> app/console doctrine:generate:entities CompanyChildBundle

这会自动修改核心和子实体定义:

核心包实体: http: //pastebin.com/kfQRxcnm

子包实体: http: //pastebin.com/UdiPP9xX

问题!

所以,问题的症结在于:如果你比较 Core 和 Child 包中的 setLand 函数,你会发现声明是不同的:

public function setLand(\Company\CoreBundle\Entity\Land $land = null)
public function setLand(\Company\ChildBundle\Entity\ChildLand $land = null)

错误:(

不幸的是,不同的类型提示会导致发生 PHP 严格错误,例如:

PHP Fatal error:  Class 'Symfony\Component\Debug\Exception\ContextErrorException' not found in ... Company/ChildBundle/Entity/ChildPackage.php on line ...

Runtime Notice: Declaration of ... should be compatible with ... in ... line ...

错误的原因

在对为什么这是一个问题进行了一些研究之后,我在几个地方读到更改子类中的类型提示会破坏类型提示合同(请参阅这篇文章:Is there a way to redefine a type hint to a descendant class when extends an abstract class ? )。

选项?

有一些明显但不太理想的选择:

  • 我可以很容易地抑制严格的通知,但我的开发经理对不得不在我们的 CI 流程中创建雪花异常的前景犹豫不决。
  • 我可以手动编辑学说生成的代码以删除所有类型提示,或确保子类类型提示与父类相同。这样做可以使代码工作,但我可以看到它很乏味,除非我编写一些脚本来为我管理它。
  • 我不能使用命令行工具并手动手工制作我的实体和子实体。我宁愿能够用脚本自动化这个:(

我的问题!!!(最后)

我的问题是,是否可以使用命令行工具来做我想做的事情?理想情况下,我希望能够执行原则控制台命令来生成实体存根、getter 和 setter,而无需手动干预来修复子类中的类型提示。如果这不容易实现,那么下一个最佳选择是什么?

感激

谢谢!

4

1 回答 1

4

I'm not exactly sure what process you'll use in order to define the entities, but in order to usefully create persistable entities with Doctrine such as GenericEngine and FordEngine, you want @MappedSuperclass

http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#mapped-superclasses

It's the Doctrine equivalent of an abstract class.

There are some other interesting inheritance tricks on that page linked above. They might help you.

As far as generating this stuff automatically, it could be doable but above my pay grade at +50 reputation points. :-) Doctrine can help you generate code templates for your entities, but really, time designing the entities and their relationships is better spent than time coming up with a magic command line combination.

(Myself, I'd have a Manufacturer entity and then have one-to-many relationship between the Engine and the Manufacturer. But that's not what you asked. :-)

于 2013-08-17T02:31:58.347 回答