PHP: Doctrine & twig, many queries executed for joins - symfony

I've recently started rebuilding a old PHP application using Silex, Doctrine and Twig.
One of the main entities is "issue" (It's a issue tracking system), the issue has relations to many other entities, like "status", "Owner", "creator" , etc.
I've created all entities as doctrime ORM entities and defined all relationships.
From the controller, I fetch one "issue" and send it to the twig template like this:
$issue = $app['orm.em']->getRepository('MMW\Entity\Issue')->find($issueId);
In the twig template i can easily print out the related entities, like:
{{ issue.status.name }}
and
{{ issue.owner.name }}
It works like a charm, but when I enable logging to see what queries are send to the database like this:
$em->getConnection()
->getConfiguration()
->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
I notice that for each join, a separate query is send to the database. I would think that performance wise, one query with SQL joins would be much faster.
Should I build my application in a different way, maybe use the querybuilder in the controller to fetch the exact columns and entities I need? Or is there a way to force doctrine to build the query in a different way?
Or should I just not worry about it and leave it as is...?

You should use Doctrine fetch joins to fetch the entire entity and prevent this way to access for every field. I recommend you to read the Doctrine documentation: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#joins

Related

Edit Symfony entity from the frontend

I have a Symfony app using multiple entities.
A third-party analytic tool plugs to my database to create reportings.
What I would like to achieve, is being able to update the Symfony entity from the frontend in order to add new fields to the database tables (in order to get the new fields showing up in the reporting tool).
Anyone has a idea on how to achieve that?
Thanks in advance.
If i understand correctly, you wan't to be able to add fields to your entity dynamicaly.
I don't know if this is doable and if so, it would probably be messy and unsecure.
What you can do however is using sub-entities with dynamic key => values fields.
You should have one main entity, an entity with the list of your dynamic fields, a many to many relation between your main entity and your fields entities and a third entity with the actual values from those fields.

doctrine:schema:update wants to create an already existing view in symfony 2.8

I have an existing view in my SQL database "view_account" which represents a account entity. This view is read only and has no primary_key field. Actually it has a primary key "id" but the field is not declared as primary key. I can also not change the table design, because its an automatic export from another application generating this tables (the automatic export is every week).
But thats not the problem cause doctrine don't care about "primary key" flag in the database until you don't update the schema.
But whenever i try to "doctrine:schema:update --force" doctrine wants to create this table. How can i ignore this view (or better the entity) from updating by doctrine? Marking the entity read_only with doctrine annotation is not working. Extending a own update-command will also not work, as i found out, it will not work since doctrine 2.4.7 to extend the doctrine-schema-update command (the update command method is ignored in any way).
Whats the best solution?
Edit:
I also tried to configure two entitymanager. One for the "internal" entities and for the "foreign" entities. Since all entities are linked to each other on some point, it is also not possible to have two separated manager don't knowing from each other entities.

How to detect if entity exist in database

I have 2 entities, User and Profile. Profile has in-symfony relation with User, but there is no in-database relation (no foreign key, no cascade) - only simple int column named user_id and nothing more.
Problem is obvious: when i delete user - associated profiles persists, but their user_id points to non-existing user row.
Since I use in-symfony relations when i fetch profile from database it fetches also related user entity. I expected that if there is no row with specific ID, it would just leave null or at least throw an exception or something.
Problem is that symfony creates empty User entity object with only id set. rest of its fields are null.
I know solution would be to create FK, constraints etc ... but I'm not allowed to touch anything in database schema.
How can I manage this problem ? I could even leave those empty object if only i had simple way to determine if they exist in database inside TWIG - so i would know if i can display {{ profile.user.email }} for example.
Fast and dirty solution, as you ask, is to use this test: http://twig.sensiolabs.org/doc/tests/defined.html
But I strongly recommend to rework your entity relations.
Found solution: its fetch: EAGER set to problematic mapping in doctrine.
By default doctrine uses LAZY fetching what results in using Proxy classes generated by doctrine for related entity. That class is almost same as real entity class. Difference is inside getter methods that before returning value performs fetching entity from database.
At this point, when you call getter on such proxy, doctrine tries to find entity in database using its ID, and since it doesn't find anything it throws exception.
When using EAGER fetching doctrine performs fetching of related entities on the same time when it fetches main entity and if it doesn't find it then sets null on relation field.

How to log an entity that has collections?

I want to log all changes of an entity. I looked into Loggable doctrine extension as provided by the StofDoctrineExtensionsBundle.
I got it working for fields that store simple data, e.g. string and integers. But my entity also has ManyToMany relationship to another entity, e.g. Tags.
I am getting this error:
InvalidMappingException: Cannot versioned [tags] as it is collection in object - Hn\AssetDbBundle\Entity\Asset
Is there a way to log an entity with its relationships? I don't mind switching to another bundle.
Currently no bundles/extensions have this functionality out of the box. One option would be to implement it yourself. This can be done by making use of Doctrine Listeners. Particularly you need to listen to postUpdate and postPersist events - these happen when entity is updated and created and store your Tags there.
Another option is to get rid of ManyToMany relationship. For this create an intermediate entity AssetTag that would have OneToMany relationship to both Asset and Tag. After this is done, you can use EntityAudit Doctrine Extension, which supports this type of relationships.

Doctrine - Get entity and relationships in one query

Am I missing a point with Doctrine? It's been very useful for some scenarios, but for the basic scenario of retrieving an entity using an Id (say using find() or findOneBy()) why do you see a query being fired off for every relationship to populate the main entity's properties?
Surely with the mapping/annotations I've created, Doctrine should be capable of a few joins and one query, without having to write a DQL query for the retrieval of each entity.
Or, as I'm predicting, have I missed the point somewhere!
Just add the aliases of related entities to select part of your query.
Let’s say, you have Book related one-to-many to Cover, and you want so select some books with their covers.
With query builder, use:
->createQueryBuilder()
->select("book, cover")
->from("Book", "book")
->leftJoin("book.covers", "cover")
With query, use:
SELECT book, cover FROM Book book LEFT JOIN book.covers cover
As the result, you will receive collections of Book with prepopulated $covers collection.
Because the relationships are hydrated only when needed - by default Doctrine uses a lazy-loading strategy.
If you already know that you will access the related entities, you should build a DQL query that retrieves the record AND the related entities.

Resources