Symfony6/Doctrine: when flushing, check if record of relation already exists - symfony

I have several entities with several relations. They have one "starting" entity. When I want to persist data to my database, I set the data to each entity (implicitly with a method I wrote, because I import that data from an xml), but only persist and flush the main entity. I used cascade:persist in the entities accordingly. And all that works just fine.
But: There are entities (the OneToMany side) that should check in the database, whether or not the record already exists and only set a new record, if not. And if the record exists the ManyToOne side should get that foreign key, that already exists.
Is there an easy way to tell doctrine to do so on my single persist/flush of the main entity?
edit
Maybe I can simplify the question to:
Is it possible to flush an object and doctrine will check if this record already exists in the database (in one query)? Or do I have to do make a query to check for existing records first and then a second query with my data to be set?
edit end
Thanks a lot for your help
David

Related

How to know the last preremove symfony listener

I have several entities with relationships between them, and when I delete an entity related to another entity, the two entities are deleted. This is what I want. However, I would like to know which one is deleted last. So I have a listener "preremove" which is called twice. Once for the first entity, a second time for the second. But I do not know which one is deleted last. Do you have any ideas? thank you in advance
Check tables foreign keys. If your tables have OneToMany relation, record which stores foreign key, will be deleted first.

How to set a deleted property to true rather than removing a related doctrine entity in Symfony

I'm building an app that allows a user to create reports for advertisers. The entities are set up so that there is a relation between the Report object and the Advertiser object - so that the advertiser has a getReports() method to get them.
I would like to change the app so that instead of actually deleting entities, that it simply changes a "deleted" property to true. That part is no problem, but I'm unsure how to make it so that the getReports() on the Advertiser entity only returns reports for the advertiser that have a deleted property of false.
Please let me know if you have any suggestions how that should be done in accordance with Symfony best practices.
You should look into Gedmo Doctrine Extensions. http://atlantic18.github.io/DoctrineExtensions/
Specifically for your case:
http://atlantic18.github.io/DoctrineExtensions/doc/softdeleteable.html
TLDR; they allow you to configure behavior of your entities in a way you desire, so for example when you "delete" an entity, Gedmo's listeners would set it's deleted value to a current datetime. Now you'd still have that record in your database but with not null value of deleted column marking it 'soft deleted', so when querying, it wouldn't be returned (because Doctrine knows how to query these stuff and would add a condition i.e.: ... where deleted ...) unless you explicitly say you want to see those soft deleted records.

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.

LINQ to Entities, several one-to-one references to the same tables and naming

I've started porting a .NET SQL Server application to LINQ to Entities. I have (among others...) one table called Users, and one called Time. Time is reported on a specific user (UserId), but it is also recorded which user made the report (InsertedByUserId) and possibly who has updated the Time since insert (UpdatedByUserId). This gives me three references to the table Users.
When I generate a .EDMX from this I get three references to the table Users: User, User1 and User2. Without manual edit I have no way of knowing which one refers to the UserId, InsertedByUserId or UpdatedByUserId field.
How do others solve this? Maybe it's not necessary to register ALL references, and stick with InsertedByUserId and UpdatedByUserId as ints?
(The manual edit wouldn't be a problem if the database were never updated, but as we make changes to the database every now and then we occasionally have to regenerate the .EMDX, thus removing all manual changes.)
Thanks in advance!
Jos,
Generally when I make my foreign keys, I name them accordingly. From the Entity designer you can differentiate between the different Navigation Properties (ie User, User1, User2) by looking at the FK association (as long as you named your foreign keys distinctly). For Instance I have a ModifiedById and CreatedById field in each table. Both fields reference my SystemUser table, My foreign keys are named like this: FK_[TableName]_SystemUser_CreatedBy and FK_[TableName]_SystemUser_ModifiedBy.
You should notice that in the Navigation properties you can see the Foreign key. You can also modify the name of the Navigation Property (which is in the Conceptual Side "CSDL portion" of the EDMX), and this change will stay when you update your EDMX from the database.

Resources