I'm writing constructors for my classes in a Doctrine2 application, let's say Fruits, Apple, Bananas.
Fruits is the parent class, where Apples and Bananas inherit from Fruits using single table inheritance on field type.
On the Doctrine2 documentation page, there is an example provided for single table inheritance. If we are always discriminating using Single Table Inheritance, should the base class Fruits be abstract because the discriminator field must always be set? If so, should the constructor for Fruits also be protected to prevent this behavior?
As there are no methods in your parent class "Fruits" that you need to redeclare I don't think there is an explicit need for it to be declared as abstract.
Also you may find a use case where you may want an instance of "Fruit" to be persisted (undetermined as to what type of fruit it is). Marking the parent as abstract will prevent you from being able to do this.
Maybe fruit is a bad example. But the Person example they have in the documentation is better. Employees will inherit Person definitions. But I may also want to persist just an instance of Person, undetermined of type. Hence the "person" = "Person" in the #DiscriminatorMap.
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/inheritance-mapping.html#single-table-inheritance
Related
I am still trying to understand polymorphic associations in Doctrine2.
As I understand it, basic polymorphic associations work by using inheritance. If, for example, I had tables/classes OWNER, CAT and DOG, then the way to enable $owner->pet to point at either the CAT or the DOG table, would be to have them each extend a fourth class, PET, which is known as a mapped superclass. Then $owner->pet could return either a CAT or a DOG depending on what had been assigned, and Doctrine2 would be able to distinguish them.
That's simple enough. But what if I want to have two polymorphic associations which can point at the same object? For example, lets say that I have a table of ADMIRALS, each of which could command a FLEET or a PLANET. Let's also say that I have a table of SECTORS, each of which could contain a PLANET or a MOON.
Let's assume that I want $admiral->command to reference both PLANETS and FLEETS, and that I want $sector->contents to reference both PLANETS and MOONS. PLANET can't extend both command and contents as mapped superclasses. Is there a different way to make this work?
you can try ResolveTargetEntityListener see
you can point admiral's command property to an Interface, which is implemented by both PLANETS
and FLEETS
the same is with sector's contents
This seems simple but I can't get it right:
There are three entities: Fruit, Vegetable and Snack. Snack has the fields id, time and food. Food is a reference to either one fruit or one vegetable. So it is basically a many-to-one/one-to-many relationship as one snack will always only hold one food. But there is more than one target entity.
How would I map this in Doctrine2?
A simple solution I would have used before knowing Doctrine2 would be to use two fields: food_type and food_id. But how can I make a connection from food type to the correct entity? I thought about an array of JoinColumns but can't find a way to connect the correct entity. I also had a look at mapped superclasses because there is a DiscriminatorColumn, but it also seems to be the wrong approach. If I get it right the superclass can't be an entity itself - so I cannot create a food entity.
Any help is appreciated. I'm sure I am missing something simple here.
You can create a (abstract) mapped superclass called Food, which can hold some basic information for Fruit and Vegetable.
The keyword for your question is inheritance mapping, this is the documentation for it: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/inheritance-mapping.html#inheritance-mapping
Then you could reference this mapped superclass in your entity relationship.
Is it possible to have a CTI in Doctrine 2 that does not shared the autoincrement? For example, i have a Pet entity and two sub-classes, Cat and Dog. However, if i create two dogs and one cat, the next ID for BOTH entities will be 4. I wanted Dog and Cat to have it's own autoincrement.
I don't see how would this work, regardless of doctrine.
What if you don't know which entity to expect and have only the id?
For example get the Pet with id 4?
You can't query by base class, which IMHO breaks the purpose of inheritance.
With CTI you get separate tables, but still it is just plain inheritance, CTI is just a object-relational mapping shema.
From the object model perspective having two entities of same type with the same id just doesn't make sense.
So you can either stick with what you have, or get rid of the inheritance completely and manage Cat and Dog as two independent entities. I would suggest you stick with the first option.
Also, with CTI there is no autoincrement on Cat and Dog, only on Pet. Child tables just copy the ID from parent, regardless how the ID was generated.
I have a polymorphic association (Class Table Inheritance) and I need use DQL to query entities of a specific child class wich can be done using "x INSTANCE OF Entity" in WHERE clause. Now I need to put conditions specific for that child class but I get this error:
"Class Person has no association named student_field_1"
Person = Parent Class
Employee = Child class
Student = Child class
is there any way yo cast of somehow tell Doctrine that the Person is actually a Student and to allow me to put Student fields in the WHERE?
It sounds like a "Mapped Superclass" would be more suited to what your trying to do as it doesn't require an explicit link between parent / child, its just simple inheritance.
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/inheritance-mapping.html#mapped-superclasses
With Class Table Inheritance your required to provide discriminator map that links the two entities through a key.
"The table of a child class should be linked to the table of a parent class through a foreign key constraint"
If you're only querying students, then why don't you just do this?
SELECT s FROM Student s WHERE s.student_field_1 = ...
I have an object model that contains a class with several subclasses.
The subclasses share a few fields from the parent, but they each have
their own fields as well.
I'm using the column_aggregation inheritance type to do this because I
want to be able to polymorphically store objects of the parent class
type, but retrieve objects of the subclass types.
So far, I can retrieve the objects with their subclass types intact.
My problem is that when I call getColumns() on any of the subclass , I
get all the fields for the aggregated table, so I see every field from
all the subclasses together.
Is there a way to only get the fields that actually belong the
subclass?
Design-wise the output of getColumns() is correct (it merely returns all columns of the aggregated table). I think Doctrine_Table->getColumns() is oblivious to the fact that the table in question has sub-classes. Try to use Doctrine_Table->getColumnDefinition() or as a last resort Doctrine_Table->getColumnOwner($column) to infer which columns belong to which sub class.