Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
303 views
in Technique[技术] by (71.8m points)

php - ZF2 + Doctrine 2 - Child-level discriminators with Class Table Inheritance

Much asked on SO and around the web with regards to ZF2 with Doctrine 2 and using Discriminators is: how do you not declare all child Entities on the parent Entity? Especially when you have multiple modules?

The short answer is: do not declare a discriminatorMap. Doctrine will handle it for you.

The longer answer is below.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A popular article on how to be able to declare your child Entities, on the children Entities, instead of the parent, is this one.

However, Doctrine 2 has changed somewhat since it was written, e.g. the AnnotationWriter no longer exists.

There, however, is a simpler way, as I mentioned in the question: do nothing.

To now use Discriminators using the “Class Table Inheritance” method (as opposed to “Single Table Inheritance”) is to NOT DECLARE a Discriminator Map! (Not sure if this will also work for STI…)

I found an old ticket on Github that explains the same issue as this answer and which many people still have, that declaring on the parent makes no sense. After reading through that, I dove into the code and re-read the docs, carefully.

Also, if you’re reeeeaaally careful when reading the docs, it says this is possible, by not saying it.

Quoting:

Things to note:

The @InheritanceType, @DiscriminatorColumn and @DiscriminatorMap must be specified on the topmost class that is part of the mapped entity hierarchy.

The @DiscriminatorMap specifies which values of the discriminator column identify a row as being of which type. In the case above a value of “person” identifies a row as being of type Person and “employee” identifies a row as being of type Employee.

The names of the classes in the discriminator map do not need to be fully qualified if the classes are contained in the same namespace as the entity class on which the discriminator map is applied.

If no discriminator map is provided, then the map is generated automatically. The automatically generated discriminator map contains the lowercase short name of each class as key.

Of course, the above piece of documentation does explicitly state that a map would be generated if none was provided. Though it contradicts the first thing to note, which is that the @DiscriminatorMap must be provided on the topmost class in the hierarchy.

So, if you were to stretch your classes across several modules (as I assume that’s why you would be reading this), do not declare a discriminator map!

I’ll leave you with an example below:

<?php
namespace MyNamespaceEntity;

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * // NOTE: No @DiscriminatorMap!!!
 */
class Person
{
    // ...
}


<?php
namespace MyOtherNamespaceEntity;

/** @Entity */
class Employee extends MyNamespaceEntityPerson
{
    // ...
}

When you use the doctrine CLI command to check your entities, you’ll find this is correct.

Also, check that it fully works by using the entity checking command:

./vendor/bin/doctrine-module orm:mapping:describe “MyNamespaceEntityPerson”

Near the top of the response of that command will be this line:

| Discriminator map | {“person”:”My\Namespace\Entity\Person”,”employee”:”My\Other\Namespace\Entity\Employee”}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...