Doctrine possible to reverse engineer inverse associations? - php

I have database with about 100 tables and I'm using Doctrine 2 as my Data Mapper. I successfully generated entities for my tables, however, I noticed that many-to-one relationships didn't generate bidirectionally. Only many-to-one part of the relation generates, the one-to-many does not.
For instance in my Company entity I have
/**
* #var \User
*
* #ManyToOne(targetEntity="User")
* #JoinColumns({
* #JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $user;
but I don't have anything pointing to the Company entity in User.
I am aware that Doctrine doesn't do this OOTB it says so in their documentation but I was wondering if there is a way to get around this limitation.
Writing 300+ relations by hand is a task I don't want to undertake.
Is there perhaps an alternative Data Mapper library for PHP that can solve this for me?
Thanks in advance.

I ended up using Propel because it generated everything wonderfully, albeit I ended up with some very large files (14k LoC).
It seems there simply isn't a PHP ORM that does everything right.

Related

"Real" orphan removal with Doctrine/MySQL

I have two entities linked together by a ManyToMany relationship in a Doctrine/MySQL project.
A Client entity:
class Client
{
[...]
/**
* #ORM\ManyToMany(targetEntity="ClientTag")
* #ORM\JoinTable(name="clients_tags")
*/
protected $tags;
}
And a ClientTag entity:
class ClientTag
{
[...]
/**
* #ORM\Column(type="string", length=45)
*/
protected $label;
/**
* #ORM\Column(type="string", length=7)
*/
protected $color;
}
So I have the ability to associate multiple clients to one tag, and vice-versa, great.
But I can't find a way to automatically remove a tag when there is no more clients referencing it.
I tried to use orphanRemoval on the ManyToMany annotation but it doesn't do what I thought.. Orphan removal should imply exactly what I described above but it removes the tag when the reference to its parent is removed, not considering other entities like I need to.
If a client removes a tag but this tag is still used by 2 other clients, I don't consider it "orphan" as it still has one or more entities referencing it.
Of course I could solve the case by doing a query and removing it myself if I don't find any parent, but I wonder if Doctrine or MySQL have a built in way to do this (that will be far more optimized) ?
Any idea?
Thanks for your help.
Officially orphanRemoval isn't supported for ManyToMany relations in doctrine.
http://docs.doctrine-project.org/en/latest/reference/annotations-reference.html#annref-manytomany
The orphan removal in this case is ambiguous.
You can either just understand the relations (the jointable entries) to the deleted entity as the orphans or the related entity.
From a database point of view it would be the jointable entries.
From an ORM point of view it's the related entities.
Thing is both ways are correct depending on the use case. For example in an Article <-> Category relation you would want to remove the article from all associated categories on deletion, but you wouldn't want to throw away the whole category just because it's empty at this moment.
I'm guessing that's the reason why Doctrine doesn't officially mention the orphanRemoval option for ManyToMany because it's unclear and to fully support both variants the current implementation isn't enough.
Hope that was somehow understandable.
In your case though you'll probably need to clean up unused tags yourself.

Whats is the use of annotation group in doctrine

I am new to doctrine, In my symfony project all the entity annotation linked with groups but I am not getting what is the use of Groups.
/**
* #ORM\Column(type="string", length=64)
* #Groups({"public","details"})
*/
I have newly added the field in my entity file, while executing the schema update getting (newly added field) was never imported.
What is groups and how it's useful.
Groups is not part of doctrine, and is not necessary unless you need serialize objects to use json or xml (Rest API, etc)
http://symfony.com/doc/current/components/serializer.html#attributes-groups
http://symfony.com/blog/new-in-symfony-2-7-serialization-groups
It allows to serialize just selected group of attributes (eg. to skip internal ones).
Read more here: http://symfony.com/blog/new-in-symfony-2-7-serialization-groups

Doctrine 2: Load entity and childs count

I have these two entities:
Message entity
class Message
{
/**
* #ManyToOne(targetEntity="User")
* #JoinColumn(name="author", referencedColumnName="id_user")
*/
protected $author;
User entity
class User
{
/**
* #Id
* #Column(type="integer", nullable=false, name="id_user")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", nullable=false)
*/
protected $name;
I need to get the total of messages of user and its data in order to echo something like this:
echo $user->getName() . " have {$user->totalOfMessage()}";
I now that I can make a relation in User entity to get a message collection. But I don't know if it necessary only to get the size.
Well, I found the answer. At least one good option.
As of Doctrine 2.1 you can mark associations as extra lazy. This means that calling $user->getMessages()->count() won't load the messages, it will just issue a COUNT query to the database.
You can read about extra lazy collections here: https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/extra-lazy-associations.html
I've recently been trying to get the EXTRA_LAZY loading working and found what I think is quite a major mistake in the documentation as shown on page:-
http://www.doctrine-project.org/docs/orm/2.1/en/tutorials/extra-lazy-associations.html
I expect that most Doctrine users may realise that the fetch="EXTRA_LAZY" needs to be put on the 'owning' side of the ManyToMany relationship but the example shows the annotation being added to a line which contains 'mappedBy' which is NOT the owning side?
By adding the fetch="EXTRA_LAZY" directive to the non-owning side it gets completely ignored as I now know it should be. I think this should be more clearly stated in the documentation.
I could not find any article anywhere explaining this after exhaustive searching so I'd say this is probably worth an amendment to the docs?
In our use case it's made a particularly intensive block of processing which used quite a number of 'contains' calls and which constantly crashed due to exceeding memory limits into a quick process which now executes orders of magnitude faster.
Hope this info helps someone out there...

Doctrine : One to one to one relation?

I'm making entities for a Symfony2 project at work.
I'm trying to make a system that controls the access to certain resources in function of an organisation (a company) and of a role. To sum it up, roles are the same for all the companies, but a company may make a resource available for a role, as another may not want to.
As for resources, they represent some actions and contents, such as the creation of this, the edition of that, and so on...
I attempted to solve this problematic with the following entity. It represents a one to one to one relationship between my three entities Organisation, Role and Resource.
I wanted to know if that kind of relation was possible/good, or if there is another way to manage resources.
/**
* #ORM\Entity
*/
class Organisation_Role_Resource
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Organisation")
*/
private $organisation;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Role")
*/
private $role;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Resource")
*/
private $resource;
Do you have any piece of advice on how to solve this problem?
Is there another/better way to represent resources (which are, in fact, pages and links) and to manage their access?
While this might be quite valid approach you would be really reinventing the wheel.
Symfony2 has it all implemented already as 'Access Control Lists' or (ACL):
http://symfony.com/doc/current/cookbook/security/acl.html
Check it out.... I think it covers everything you need...

Getting associated entries in Doctrine 2

I've decided that it would be a good asset to get familiar with an ORM and went for Doctrine 2 as the ORM of choice.
I'm working on a test project to learn the basics of Doctrine. Although most people usually go with a blog, I've decided to make a basic app in which you can save and track orders. My database schema would be as follows:
User
id
name
Product
id
name
price
Sales_order
id
user_id
product_id
quantity
unit_price
Hence, my Order model looks like:
/**
* #Entity
* #Table(name="sales_order")
*/
class Order {
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
private $Id;
/**
* #OneToOne(targetEntity="User", inversedBy="user")
*/
private $user;
/**
* #OneToOne(targetEntity="Product", inversedBy="product")
*/
private $product;
/**
* #Column(type="integer", nullable=false)
*/
private $quantity;
}
Now, the question is, is there a simple way of accessing all the orders from the user model? Should I write DQL (doctrine query language) for these kind of basic stuff or is there a way to easily get associated entities? I mean, there wouldn't be any point to this otherwise, right? Also, am I doing these associations correctly? I'm really confused in this very basic model... Detailed help is really appreciated. Thank you.
Firstly, don't worry too much about the database design. You should design your entities and use the SchemaTool.
Now, the question is, is there a simple way of accessing all the orders from the user model?
Do you mean access all of the orders from the user model, or access all the orders associated to a user?
If you meant the former, well you are doing things wrong (see below). If you meant the later, you should setup a bi-directional relationship between orders and users. (BTW, it would be OneToMany not OneToOne as one user would likely have many orders).
I'm really confused in this very basic model...
I think what you having trouble with - along with many PHP programmers - is the fundamental understandings of the DataMapper pattern and ultimately Domain Driven Design as well. Remember, you are dealing with persistable objects, not database tables.
I cannot provide detailed information here because I'd be writing a book, hence this I would recommend you get a book on Domain Driven Design to help kick start with the principles. There are a few good online resources available, like a series of blog posts by Federico Cargnelutti, however they aren't specific to Doctrine 2.

Categories