Can entity tracking be turned off? - symfony

I've got multiple entities set up with their respective repositories, all working properly. However, Doctrine seems to populate proxies where I don't want them to be populated.
I've got an entity called Item, which references a Category, both by having a $category_id and a $category field. The latter has the relationship set up with #ORM\ManyToOne() and #ORM\JoinColumn(), working correctly.
In my controller, when I'm querying Items, I receive a list of items with proxies to the related categories, which I can strip out from my response, identifying them as being proxies. However, if for whatever reason, I also query Categories in an unrelated query, the item-related query return with not proxies but actual hydrated Category instances, which I don't want.
$this->categoryRepository->findBy(...);
...
$items = $this->itemRepository->findBy(...);
return $this->respond($items);
Here, $items[0]->category will have been populated by the framework by the time the execution reaches the return statement.
Is it possible to turn this behaviour off?

You can specify the fetch policy on a relationship to be EXTRA_LAZY, this will fetch the least amount of date on execution as possible. Per the docs:
With Doctrine 2.1 a feature called Extra Lazy is introduced for associations. Associations are marked as Lazy by default, which means the whole collection object for an association is populated the first time its accessed.
So in your #ORM\ManyToOne() annotation, add a parameter: fetch="EXTRA_LAZY" to the others.

Related

Symfony CollectionType update Entities

I can't believe this hasn't come up for other people, but I'm unable to find a solution.
Let's say I have two entity types, A and B with a one-to-many relationship. A has a collection of Bs.
The form for A has a CollectionType for the Bs, with a custom entry_type for B, allow_add and allow_delete set to true. When the form is created/populated/rendered, the Bs' fields are identified by their index in the collection. When the form is posted back, the fields are mapped back onto the B entities according to the index again.
What if the database in the mean time decided to return the Bs in a different order? Then the values get swapped around on the Bs! I can't have that, as other entities will reference the Bs and now they've changed their meaning!
Even if the database doesn't change the order, the same issue appears when a B is deleted: The fields get shifted through the Bs and a different one deleted! (Ok, I'm not a 100% certain this happens, as there's a gap then in the numbering of the posted fields.) I've found this similar question where it does happen when another one is created (Symfony CollectionType regards deletion+creation as a modification of an item), but that sort of drifted from the issue and there's no usable answer.
How do I make sure the form is updating the entities the user actually edited?
I already tried to render the Bs' IDs as a HiddenType, but then the form rightfully complains that the ID has no setter. It would probably force an ID on the wrong B anyways and Doctrine doesn't like that. I suppose I could add the Bs as unmapped and copy the values over to the correct objects manually, but that would defeat a good chunk of Symfony's form system.
I've used CollectionType before, but not for entities that are referenced elsewhere. I would then delete all of the previous entities and create the collection anew from the posted data. But I can't do that now, can I?
Since doctrine 2.1, it's possible to change how associations are indexed. This will allow you to use the id as the collection key (as the field has to be unique):
#OneToMany(targetEntity="B", mappedBy="A", indexBy="id")
You might also need to enable orphanRemoval so that the data is actually removed instead of the relation just set to null.

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.

Use a repository with JMS serializer

I have a Symfony 3.4 projet with a REST api. I use JMS serializer.
I have a entity User and I have a route /api/user which return the user id, name , ...
I also have a entity badges which has a relation many to many with user (so a user_badge table). Like I read, when the pivot table have extra column (like in my case on user_badge), I need to create two relation many to one to link my user to badges.
In my route /api/user I add the return on my badges with JMS, I return my badge id and the achievement date (the extra column) from user_badge with the method getUserBadges from my entity User.
But now I want to order by the badges using a column from the badge entity.
How can I achieve this ? The fact than my model user can't access the badges without a heavy foreach. I need to make a request to getting all the badges in the correct order and passing this to JMS.
(I don't know which source file I should provide, cause I don't really know how to achieve it)

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.

Complex Rule in Drupal involving multiple entities

I need to create a fairly complex rule in Drupal - I am willing to use either code or the interface to do so.
I am more familiar with the interface, however, as opposed to the Rules API.
Anyway, the rule will be as follows:
It will happen based on a form submission from entityforms (which is one entity). It will take the checkbox value of a field (not just the true or false, but rather the value submitted when a value is true or false). It will convert this number to an integer.
At this point things get interesting - I want to create a new entity of registrations (a different entity), which as far as I can tell, means I'll have to bring a registration into scope. I also need to bring node (and not just node: type and other data selectors, but specifically node) into scope, because the next step requires it.
So at this point, I should have three entities loaded into scope:
entityforms
registration
node
I believe the best way to bring registration into scope would be entity is of type? The documentation page says that content of type should be appropriate - but that seems like it might be related to the specific use case of the example - not in my more complex example where registration isn't the first entity dealt with, but rather a second.
https://drupal.org/node/1463042
So anyway, if all three of these entities is called in correctly, the ultimate result should be the following:
Value from boolean field (not the straight 1 or 0, but whatever the value to be submitted is switched to) from the entityform is converted to an integer, and inserted where entity host ID is required. In the section where host entity type is the value should be node.
I am also open to alternative suggestions if this seems overly complex or poorly architected.
The Host Entity Type cannot be of Entityform? Why be a Node since a Registration can be attached to any entity? Then you will get the id of the Entityform as also as any other fields from that entity type instead of Node. Next steps are the same.

Resources