I have this kind of relationship in the database as follows, which I even don't know how to name:
Doctrine generates 3 entities, which is right, creates proper mappings for t1-t2 relation, but then uses nonexisting entity t1_has_t2 for t3-t3_has_t1_has_t2 relation. Is there a way to implement this kind of relationship in Doctrine without turning t1_has_t2 into useless entity.
Related
I'm migrating the DBAL of a ZF3 application to Doctrine and want to go ahead step by step. Currently I'm using a hierarchy of Mapper objects. Each entity in the like FooEntity hierarchy has an according FooMapper. Saving of nested entities is performed by nested Mappers. Every Mappers saves its entity with Zend\Db\Sql\Insert or Zend\Db\Sql\Update and calls the proper Mappers for the sub-entities like BarMapper for BarEntity.
Now, before I start with Doctrine's convenience features like cascade={"persist"}, I want to keep the Mapper's hierarchy and just to perform the saving of the top level of the nested entity with persist(...) & flush().
But when I try it
public function save(AbstractDataObject $dataObject)
{
$newLogicalConnection = $this->logicalConnectionMapper->save($dataObject->getLogicalConnection());
$newUser = $this->userMapper->save($dataObject->getUser());
$dataObject->setLogicalConnection($this->entityManager->find(LogicalConnection::class, $newLogicalConnection->getId()));
$dataObject->setUser($this->entityManager->find(User::class, $newUser->getId()));
$this->entityManager->persist($dataObject);
$this->entityManager->flush();
return $dataObject;
}
I get an error
A new entity was found through the relationship 'MyNamespace\DataObject\AbstractEndpoint#externalServer' that was not configured to cascade persist operations for entity: MyNamespace\DataObject\ExternalServer#000000006098ccff0000000068c23676. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'MyNamespace\DataObject\ExternalServer#__toString()' to get a clue.
So, Doctrine seems to try saving the whole entity with its sub-entities, and this attempt fails on one of the lower levels. But why? I have not activated any cascade options and expect Doctrine to save only the top level.
Why does Doctrine try to save the whole entity and not only the top level? And how to get it saving only the top level of the given entity?
You get this error because you have a new entity (not persisted yet) in AbstractEndpoint->externalServer and this field is not annotated as cascade={"persist"}
In other words you have just created a new entity ExternalServer and did not persisted it and added it as a relation to AbstractEndpoint->externalServer entity which is not annotated as cascade={"persist"}
So Doctrine ends up having this new entity and does not know what to do with it. In order not to lost any data this exception is raised.
To fix this you can do two things:
Add $this->entityManager->persist($externalServer); right after you create ExternalServer entity
Annotate AbstractEndpoint->externalServer with cascade={"persist"}. Which you don't want to do because you want only top level entity to be saved to DB so you need to persist it manually or DO NOT add it is a relation.
And now answering your question:
But why? I have not activated any cascade options and expect Doctrine to save only the top level.
Somehow through relations in your object model Doctrine goes down to ExternalServer entity and finds it in unpersisted state. You can not save only top level of object hierarchy with link to unexisting record in relational database. If you do not want Doctrine to do it for you - you must handle this situations by yourself or remove not persisted entities from relations
I have an entity called Document. I'd like to make this entity related (many to one) to few other entities (let's say User, Invoice and Transaction). In Laravel I could easily achieve that by using polymorphic relations.
Is there any (easy) way to accomplish the same with Doctrine?
This might be what you're looking for http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html
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 need to decide which approach to choose for my MySQL DB.
Example:
PHOTO ALBUM
User - can own photoalbum
Group - can own photoalbum
(maybe more entities could own photoalbum)
Now how to represent this in DB so it will:
Work nicely with Propel (join selects etc.)
I believe one approach is called polymorphic associations. But it has its own problem and I cannot find any resource talking about polymorphic associations with propel.
Second approach would be to represent everything separated. Meaning group_photoalbum user_photoalbum. It would be cleaner in MySQL and there will be no problem with Propel, but it would double most of the code and therefore any changes will be done twice.
Can Propel work with polymorphic associations? (any source)
Is there any other approach I don't know about?
Which would you choose?
Propel inheritance. Should have read the docs whole.
propel inheritance
Propel does not support polymorphic relationships.
You are best off using another ORM, if possible.
I mean, who uses XML 2018.
#Turnadiev Nursultan, he asked whether they support the relationship,
not if you can hack your way(which is a hack).
I am in the process of upgrading from Doctrine 1.1.4 to Doctrine 2.0.6 in my Zend application.
Currently, I am working on mapping the associations between entities. In Doctrine 2's Documentation it says 'relationships maybe bidirectional or unidirectional. I am confused as to what these terms mean within the given context.
How do I determine if a relationship is unidirectional or bidirectional?
Appreciate the help.
A relationship is bidirectional if both entities contain a reference to the other.
If you omit one of those references, it's unidirectional.
Consider a typical "posts" and "tags" schema. Typically, you'd implement a bidirectional association:
<?php
class Post {
// ...
/**
* #ManyToMany(targetEntity="Tag",inversedBy="posts")
*/
protected $tags;
// ...
}
class Tag {
// ...
/**
* #ManyToMany(targetEntity="Post",mappedBy="tags")
*/
protected $posts
// ...
}
Now, imagine you decided you never (or rarely) needed to answer questions like "Which posts have Tag 'foo'?". You could omit the $posts association in your Tag entity, converting it to a unidirectional association, and take some load off of the ORM.
You could still answer that kind of question, but you'd have to write code to do it.
In fact, it's probably a good way to go in Posts/Tags scenario, as you wouldn't typically be adding/removing Posts from Tags. Typically, you'd add/remove tags from posts only. You'd only ever go from Tags to Posts when looking for "all posts with tag 'x'", which could be trivially implemented in a service class of some sort.
Same as timdev`s answer,
Unidirectional & BiDirectional is just ORM Concepts, these have nothing to do with database,
Suppose you have a OneToMany relation -
user has blogs
So you can add this to your User Entity as OneToMany Property
but obviously there exisits ManyToOne Relation
Blogs Has User
so it is optional for you to create a ManyToOne relation in your Blog Entity, If you want to access user from blog entity then add this property if you dont want then dont add,its not necessary. in both Cases (you are adding bidirectional reference or not) ORM will maintain same database structure (blog table will have user_id column) .