简体   繁体   English

使用Symfony 2 CLI工具,如何为子类生成具有正确类型提示的getter和setter?

[英]Using Symfony 2 CLI tools, how can I generate getters and setters with correct type hinting for sub-classes?

Background 背景

I am developing an application using Symfony 2 that is structured such that a "Core" bundle defines entities, relationships and fields. 我正在使用Symfony 2开发一个应用程序,其结构使得“Core”包定义实体,关系和字段。 Other bundles are then be able specialise the core functionality by inheritance, so-called "child" bundles. 然后,其他捆绑包可以通过继承来专门化核心功能,即所谓的“子”捆绑包。

Doctrine 2 annotations have been used to define a core entity called "Package". Doctrine 2注释已用于定义称为“Package”的核心实体。 A "Package" links together an architectural design and a piece of land - essentially a house-and-land package. “包装”将建筑设计和一块土地联系在一起 - 基本上是一个房屋和土地包。 I've cut the examples back to a more basic form, so you won't find definitions for Land and ChildLand in the examples below, but you can assume they have been implemented in a similar fashion. 我已经将示例切换回更基本的形式,因此您不会在下面的示例中找到Land和ChildLand的定义,但您可以假设它们已经以类似的方式实现。

Update 更新

According to users on FreeNode's #symfony channel, this is a doctrine issue as the app/console command simply invokes the doctrine console. 根据FreeNode的#symfony频道上的用户,这是一个学说问题,因为app / console命令只是调用了教条控制台。 I am using doctrine 2.3. 我正在使用学说2.3。

Here is a diagram showing the general situation that causes the issue which should help visualise the scenario: 下面的图表显示了导致问题可能有助于可视化场景的一般情况:

( imgur link to full-size image ) imgur链接到完整大小的图像 类型提示合同中断

Also, here is a link to a bug report on doctrine's issue tracker: http://www.doctrine-project.org/jira/browse/DDC-2605 此外,这里还有关于学说问题跟踪器的错误报告的链接: http//www.doctrine-project.org/jira/browse/DDC-2605

Update 2 - More detailed ERD 更新2 - 更详细的ERD

The structure of the relationships between entities has been questioned, so below is a better example of the data structure we are implementing. 实体之间关系的结构受到质疑,因此下面是我们正在实施的数据结构的一个更好的例子。

The main requirement is again to have core classes that provide a shared set of entities and fields. 主要要求是再次拥有提供共享实体和字段集的核心类。 Child classes in company bundles extend these core classes. 公司包中的子类扩展了这些核心类。

We did consider EAV at length, but in that approach we will spend a lot more time creating a platform and the tools to manage EAV data rather than satisfying the present business requirements, we won't be able to use doctrine to manage the entities as they will be defined in the database, etc etc. 我们确实考虑了EAV的长度,但在这种方法中,我们将花费更多的时间来创建平台和管理EAV数据的工具,而不是满足当前的业务需求,我们将无法使用学说来管理实体它们将在数据库等中定义等。

As time passes and I come to understand this issue better, it appears the only issue is with the getters and setters generated by doctrine's CLI tool as they break the type hinting contracts as mentioned below. 随着时间的推移,我开始更好地理解这个问题,似乎唯一的问题是由doctrine的CLI工具生成的getter和setter,因为它们打破了类型提示合同,如下所述。 This structure works perfectly when these issues are manually corrected. 当手动纠正这些问题时,此结构非常有效。

( imgur link to full-size image ) imgur链接到完整大小的图像 详细的数据结构

Generating Entities with CLI Tool 使用CLI工具生成实体

So, initially I used the command line tool... 所以,最初我使用命令行工具......

> app/console doctrine:generate:entity

...to generate the entity stubs with basic field mappings, then manually added the relationship to land (as the tool doesn't seem to support relationships): ...使用基本字段映射生成实体存根,然后手动将关系添加到land(因为该工具似乎不支持关系):

This is the resulting code: 这是结果代码:

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

child Package entity: http://pastebin.com/sjAB0XJ2 子包实体: http//pastebin.com/sjAB0XJ2

Generating Getters and Setters 生成Getters和Setter

Next, I generate the getters and setters by executing: 接下来,我通过执行以下命令生成getter和setter:

> app/console doctrine:generate:entities CompanyCoreBundle

> app/console doctrine:generate:entities CompanyChildBundle

Which automatically modifies the core and child entity definitions: 这会自动修改核心和子实体定义:

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

child Package entity: http://pastebin.com/UdiPP9xX 子包实体: http//pastebin.com/UdiPP9xX

The problem! 问题!

So, the crux of the issue is this: If you compare the setLand function in the Core and Child bundle, you can see the declarations are different: 因此,问题的关键在于:如果比较Core和Child包中的setLand函数,您可以看到声明不同:

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

Errors :( 错误:(

Unfortunately, the different type hints cause PHP strict errors to occur, for example: 不幸的是,不同类型的提示导致PHP严格错误发生,例如:

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

And

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

The cause of the errors 导致错误的原因

After doing some research as to why this was a problem, I read in several places that changing type hinting in subclasses breaks type hinting contracts (see this post: Is there a way to redefine a type hint to a descendant class when extending an abstract class? ). 在研究了为什么这是一个问题之后,我在几个地方读到,在子类中改变类型提示打破了类型提示契约(参见这篇文章: 有没有办法在扩展抽象类时将类型提示重新定义为后代类? )。

Options? 选项?

There are some obvious but less-than-ideal options: 有一些明显但不太理想的选择:

  • I can suppress strict notices quite easily, but my development manager baulks at the prospect of having to create snowflake exceptions in our CI processes. 我可以很容易地压制严格的通知,但是我的开发经理不得不在我们的CI流程中创建雪花例外。
  • I can manually edit the code that doctrine generates to remove all type hinting, or to ensure the child class type hints are the same as the parent classes. 我可以手动编辑doctrine生成的代码以删除所有类型提示,或者确保子类类型提示与父类相同。 Doing this makes the code work, but I can see it being tedious unless I write some scripts to manage this for me. 这样做会使代码工作,但我可以看到它很乏味,除非我写一些脚本来为我管理这个。
  • I can just not use the command line tools and hand-craft my entities and sub-entities manually. 我不能使用命令行工具并手动手工制作我的实体和子实体。 I would rather be able to automate this with scripts :( 我宁愿能用脚本自动化这个:(

My question!!! 我的问题!!! (finally) (最后)

My question is, is it possible to use the command line tools to do what I am trying to do here? 我的问题是,是否可以使用命令行工具来完成我在这里尝试做的事情? Ideally, I'd love to be able to execute the doctrine console commands to generate entity stubs and getters and setters without manual intervention to fix up type hints in sub-classes. 理想情况下,我希望能够执行doctrine控制台命令来生成实体存根和getter以及setter而无需手动干预来修复子类中的类型提示。 If this isn't easily achievable, what's the next-best option? 如果这不容易实现,那么下一个最佳选择是什么?

Gratitude 感谢

Thanks! 谢谢!

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 我不确定你将使用什么过程来定义实体,但是为了有用地创建具有Doctrine的可持久实体,例如GenericEngine和FordEngine,你想要@MappedSuperclass

http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#mapped-superclasses 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. 至于自动生成这些东西,它可能是可行的,但高于我的+50声望点的工资等级。 :-) 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. :-) Doctrine可以帮助您为实体生成代码模板,但实际上,设计实体及其关系的时间比花时间提出魔术命令行组合更好。

(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. :-) (我自己,我有一个Manufacturer实体,然后EngineManufacturer之间有一对多的关系。但那不是你问的。:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM