背景
我正在使用 Symfony 2 开发一个应用程序,该应用程序的结构使得“核心”包定义实体、关系和字段。然后,其他捆绑包能够通过继承专门化核心功能,即所谓的“子”捆绑包。
Doctrine 2 注释已用于定义称为“包”的核心实体。一个“包”将建筑设计和一块土地联系在一起——本质上是一个房屋和土地包。我已将示例简化为更基本的形式,因此您不会在下面的示例中找到 Land 和 ChildLand 的定义,但您可以假设它们已经以类似的方式实现。
更新
根据 FreeNode 的#symfony 频道上的用户的说法,这是一个原则问题,因为 app/console 命令只是调用了原则控制台。我正在使用学说 2.3。
这是一个图表,显示了导致问题的一般情况,应该有助于可视化场景:
此外,这里是关于教义问题跟踪器的错误报告的链接:http: //www.doctrine-project.org/jira/browse/DDC-2605
更新 2 - 更详细的 ERD
实体之间的关系结构受到质疑,因此下面是我们正在实现的数据结构的更好示例。
主要要求再次是拥有提供一组共享实体和字段的核心类。公司捆绑包中的子类扩展了这些核心类。
我们确实详细考虑过 EAV,但在这种方法中,我们将花费更多时间来创建一个平台和工具来管理 EAV 数据,而不是满足当前的业务需求,我们将无法使用原则来管理实体,因为它们将在数据库等中定义。
随着时间的推移,我更好地理解了这个问题,似乎唯一的问题是由教义的 CLI 工具生成的 getter 和 setter,因为它们破坏了下面提到的类型提示合同。当手动纠正这些问题时,此结构可以完美运行。
使用 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,而无需手动干预来修复子类中的类型提示。如果这不容易实现,那么下一个最佳选择是什么?
感激
谢谢!