In cycle orm docs some mappings have such thing as role. Text states that is it entity role (well, not informative at all). What does that mean and why do we need this roles stuff? Doctrine ORM for instance doesn't have such thing.
You can treat role as alias to class name in Doctine. Unlike Doctrine Cycle ORM can map any type of objects, including StdClass or custom models. In order to identify mapping between same class instances it uses roles.
Related
In Symfony 2.8 I have some entities which have the same fields, but for the purpose of data organisation I need them to be separate entities. Is it possible to create one abstract base class with all the fields, getters and setters and then just create new entities extending base abstract class, repeating as few as possible?
Example:
Let's say I have Movie entity, which has some people connected. People have different roles (actor, director), but let's assume they have only FirstName and LastName. I don't want to keep them in one table (with roles) for data separation purposes.
So I'd like to create one abstract Person entity, which will have FirstName, LastName, getters and setters. And then I'd like to create empty (as empty as possible) classes Actor and Director, extending Person and let Doctrine take care of the rest, so in DB I should have actor table with all the Person fields.
Is it possible to achieve something close to what I want?
It just seems like basic inheritance. Since you do not want to persist the Person entity but those which inherit from it you can define your base Entity defining Doctrine statements at everything you want to persist but the Entity itself.
Then on the child Entity you define the rest of the fields you may want to persist, configure them to work with Doctrine and on the Child Entity annotations you define the table that is going to persist that particular entity + telling the Entity to inherit its parent Doctrine configuration.
Then you will have both the parent and the child Doctrine configuration and only the table configuration on the child so every child will be persisted on its own table.
I'm currently writing a MappedSuperclass to store entity reference on an entity object.
For example to store favorites for a user, it can be any kind of model (product, category of product or whatever).
The class contains deux fields :
entityType : the class of the entity reference
entityId : the id of the entity reference
Favorite entity class will extends this Superclass, and that's work.
I'm would like to know, if there is another (cleaner?) way to do this ?
Thanks for your inputs.
As we work a lot currently with Doctrine mapping, this all depends of your buisness logic and what you want your database looks like.
If using a mappedSuperclass, basically, this entity will not appear in your database. Only entities that inherits from that mappedSuperClass will appear with its own properties and the superClass properties.
Another approach could be to use inheritance joined type that will generates this time the class in your database, event it is abstract.
Usability of your schema, even in mappedSuperclass or JOINED type, do not changes a lot of things, it's all about your preferences and your logic.
I personaly prefer the second method, as it permit to structure more your data.
I hope this helps.
Best Regards.
So I've stumbled upon this hurdle where I have to create an abstract class and a factory to create objects of more specific classes that extend the abstract class and implement more specific object methods.
Simply said, I got a SocialMediaAbstract class. Extending classes are Facebook, Instagram, and they implement a SocialMediaInterface. Facebook, Instagram etc are all saved in the db, with an id, a name and several more properties that are all used among the extending classes, hence an abstract class.
Because I want to be able to query several things from the SocialMedia Objects, and every social media platform have their own APIs for it, I made the interface and created the different classes so they can all have their own implementations of those methods.
Now, the problem is of course with my abstract class and Doctrine. Doctrine says this on their website regarding inheritance:
A mapped superclass cannot be an entity, it is not query-able [...]
Now if I had a SocialMediaFactory and threw in an ID, I would like to get the respective Object of, for example, class Facebook or Instagram back. I don't want to know exactly which SocialMedia it is when I collect them. Now that is a problem with doctrine, at least that's what I think it is.
Am I overlooking something, is the factory pattern still possible? Or should I really just remove the abstract class, and create a factory that searches in every table of a SocialMediaInterface implementing class, which seems highly inefficient and unmaintable when an application gets bigger.
Any insight or pointers would be appreciated, since I'm sure this problem must've come up more often. I tried googling and searching on Stackoverflow itself, but I couldn't get any relevant questions or answers.
Thank you very much in advance.
EDIT:
I came across this interesting possibility: Class Table Inheritance. This would mean adding:
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"facebook" = "Facebook", "instagram" = "Instagram"})
to my code. I had high hopes, but sadly enough the validator gave me this error:
[Doctrine\ORM\Mapping\MappingException]
It is not supported to define inheritance information on a mapped superclas
s 'Portal\SocialMedia\Entity\SocialMediaAbstract'.
A shame mapper superclasses are not supported.
EDIT 2/CONCLUSION:
I've decided to go with Class Table Inheritance (just like the answer below suggested). Removing the abstract from the class made it possible to still use my factory.
I am using a concrete class as an abstract class now however, which feels wrong. I've documented in docblock that no objects should be instantiated from this class.
One little sidenote: Doctrine's Entity Manager more or less already provides the Factory:
$socialMedia = $entityManager->find('Portal\SocialMedia\Entity\SocialMedia', 2);
This returns an Instagram object. I still suggest you build your own factory above it for maintainability later as the SocialMedia entity might change later on.
Some time has passed now since I worked with doctrine, but if I remember correctly, doctrine's mapped super classes are an implementation of the concrete table inheritance pattern by Martin Fowler.
In the example mentioned there, the Player is the mapped super class, whose attributes are distributed to all inheriting entities / models. The point here is that a player can't be instantiated and thus has no own id. Instead, every inheriting model got it's own id, which are all independent of each other.
I think the pattern you are looking for is either single table inheritance or class table inheritance (have a look at doctrine's inheritance types).
Single table inheritance is implemented in doctrine's inheritance type "SINGLE_TABLE", where you have one table for all entities. They are sharing the exact same attributes and same id pool, meaning you can "throw in" an id, get the object and check the type (Facebook, Instagram etc..).
The downside is that if you got in any of the entites an attribute that may be NULL, you could run into problems if the other entites don't have this attribute or don't need it. This would mean you have to set the given attribute to a dummy value in the other entities to save them into the database table.
Class table inheritance overcomes this issue by saving every entity in its own table, while still being able to share the id pool, because doctrine takes care that the common attributes are saved in the base class table, while all the attributes specific to an entity are saved in the entity's table. The tables are then joined by the id, hence the inheritance type "JOINED" in doctrine.
Conclusion:
Use single table inheritance if the classes are very similar and only differ in function definition or implementation, but have the same attributes.
Use class table inheritance if the classes have distinct attributes that would be problematic to store in a single table.
Use concrete table inheritance if the classes are not really related to each other, but only share a small amount of common attributes. But this could also be implemented through PHP's traits, which in my opinion is easier and more flexibly to use than doctrine's mapped super class. In a PHP trait you can also use doctrine's annotations, because the PHP interpreter will properly assign the annotations to the classes you use the traits in.
You should still be able to use your SocialMediaFactory with either single table or class table inheritance pattern.
What are the pros and cons of using a global base entity for all entities in my Doctrine2 model?
I am considering having all of my domain entities extend a single generic base entity, so that I can specify the target entity of an association to be the base entity class, thereby allowing that association to hold any entity in my domain.
My associations will still be as specific as possible: an Order entity will contain Product objects, not Base objects. But more 'meta'-like functionality like status log items, authorization specs, etc., can be specified very generically by defining LogItems and AuthorizationRules having an association to BaseEntity, instead of with specific items.
I am not seeing this approach anywhere, but there seems to be some use or power to having all classes extend off a base Object entity ('Java-style'). But perhaps I am needlessly overcomplicating things.
Is a base entity in Doctrine2 a good idea?
You have it all described here:
http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
You can do inheritance from the OOP point of view(php) and map it to database(you can have persons and employees that are persons as well(or people)) but you cant have the database understand the inheritance(it's done in the db abstraction layer(doctrine)).
So each class you might want to have in relation, has to be and entity, meaning that both a person and and employee have to be entities. If you do it as single table inheritance, you could relate and entity to "Person" and then it would include employees also.
http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance
http://martinfowler.com/eaaCatalog/singleTableInheritance.html
I have written quite a large and complicated query that internally uses a UNION to select from multiple tables, then returns an array of mixed type entities.
I know that best practises in Symfony say to always put the queries within the repository classes, but how do I decide which to put it in? There's no parent/child relationship between them, the two entities are completely equal.
I usually put them in the repository which I consider the most dependent entity in the context.
For instance, if I had two entities: User and Group.
Many entities might have an owning relationship with group, but you can't expect the Group repository to single handedly provide the methods necessary for every specific dependent to function.
It is the responsibility of the dependent (the owning side) to make the connection and hense provide the functionality.
So a method like getUsersInGroup(Group $group) would belong in the UserRepository.
However, you said there are no direct relationships between your two entities.
In this case, my first comment applies. Use the repository whose entity is more dependent on the other within the context of the query. Whichever entity that one is, depends entirely on you.
Do not use a repository. Repository is bounded to the context of the specific entity type, and it is supposed to be used as a Collection.
Also
A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection.
(M.Fowler)
And in your case I assume there is no Object-Relational-Mapping, given that you are using a query with a UNIONĀ of tables. I assume that your query will not return an actual Doctrine entity, right?
In that case, the query doesn't belong to the Repository pattern, and I suggest you to have a custom class where to encapsulate the big/complex query PHP+SQL code, e.g.:
namespace App\Query
class MyComplexQuery {
(optionally implementing QueryInterface)
and call it from your Controller or Service, without passing from the Repository.
In case you are defining a custom Doctrine Entity to represent the results of your UNION of entities, then use the repository of such entity.