During normalisation of JSON, I am able to modify the entities as they are processed. Say, for example, I add a new property to entities during this phase. I can do this by setting a function for processStrategy.
What I was wondering was: is there any way to do similar custom processing during the denormalisation phase, as each entity is denormalised?
There is not a way to do that during denormalization. The expectation is that you run your processing once during normalization so you won't have to do it again.
Related
I'm struggling to find a way to perform a persist() and flush() methods after the final flush (I mainly want to do it in postFlush event).
I collect the necessary entities in onFLush event (with changeSets) and wait up until all entities (which I collected) got flushed to get their id's (auto incremented).
So that I have at this point an array with all needed entities and their change sets and their id's set.
Then I want to create new entities (let's call them "traces") based on fields of previously collected entities and persist & flush "traces" in database.
But I'm really stuck here as I can't know entities id's in onFlush event, and I can't persist & flush them in postFlush when they already have their id's set.
Currently Doctrine documentation states following:
postFlush is called at the end of EntityManager#flush(). EntityManager#flush() can NOT be called safely inside its listeners.
And if I dare do this, it ends up in a recursion and php fails with an error.
Which approach may I take here?
I believe you could do a check if you aren't flushing "traces" entity and then perform your "traces" creation. That shouldn't loop.
Also you might want to look at symfony's eventDispatcher . You could dispatch your events manually, since it might be cleaner.
More details on "traces" would be helpful, from what I can imagine it is some kind of a changelog, history; so for that I might suggest EntityAuditBundle. It works pretty good with doctrine and is not hard to set up, I am using it myself.
I'm trying to come up with a reusable pattern for updating MongoDB Documents when using Spring Data in conjunction with Spring MVC.
The use case can generally be summarized by:
A document is created in Mongo using repository.save()
Parts of that document are then presented in a Spring MVC editable form.
A user submits updated parts of that document which are then saved.
If I use the repository.save() method in step 3, I will lose any data in the document that was not bound to the form. Making the form responsible for the entire document is fragile so this is where it seems the findAndModify() method of the MongoTemplate comes in handy.
To use the findAndModify() method, I've created Form objects that support a toMap() method which takes the Form object's properties as a Map and removes some of the fields (e.g. class and id). This gets me a Map that contains only the fields that I care about from the Form object. Passing the object ID and this map to an update() method on my customized repository, I build Query and Update objects that I can pass to the findAndModify() method.
Using this approach, I'm able to add fields to my objects easily and only worry about instances when there are fields I don't want to update from a form posting. Document fields not manipulated by the Form should be retained. It still seems slightly convoluted to be using both the Repository and MongoTemplate so I'm wondering if there are better examples for how to handle this. It seems like this should be a consistent pattern when working with Mongo and Spring MVC (at the least).
I've created a sample project showing how I achieve this model on GitHub. The Spock Tests show how "updating" a Document using save() will blow away fields as expected and my update() method.
https://github.com/watchwithmike/diner-data
What are other people doing when dealing with partial updates to Documents using Spring MVC and Spring Data?
If you are taking whatever the user supplies and just shoving that in the database you are running the risk of doing something dangerous like updating or creating data that they shouldn't be able to. Instead, you should first query Mongo to get the most recent version of the document, change any fields (it looks like you are using Groovy so you could loop through all the properties and set them on the new document), and then save the new, complete document.
If you are making small, consistent updates (like increasing the number of votes, or something like that), you could create a custom MongoDB query using the MongoTemplate to do an update to a few fields. Check out the spring-data-mongodb docs for more. You can also add custom methods to the MongoRepository that use the MongoTemplate.
I'm trying to persist a History entity whenever a Message gets updated. I have too much going on behind the scenes to post all the code here and for it to make sense, but I've basically tracked the issue down to the UnitOfWork::commit method. There, the UOW first loops through the entityInsertions, and finding nothing, continues on to the entityUpdates. There the UOW's entityInsertions gets updated, but since it's already past that loop, it doesn't pick up that it still needs to persist some entities. Is there any way to force the UOW to "restart" this process? If so, how? I'm using Doctrine 2.4.
Thanks for any help!
This might be the dirtiest solution ever, but what I ended up doing was basically the following...
Create an onFlush event subscriber
Inject the entire container into the subscriber (seeing as injecting only the entity manager will result in a circular reference error)
Loop through the UnitOfWork's scheduledEntityUpdates and scheduledEntityInserts (I wasn't interested in deletes)
Handle each scheduled update or insert which you are interested in (in my case, I marked each entity I was interested in with a LoggableInterface, just to know which entities are loggable)
Handle the relevant object with a handler chain (This was just my own algorithm, yours may not require this. This was set up to handle logging of different LoggableInterface objects in different ways)
Persist the entity (the actual history event) via the entity manager, and do the following:
$classMeta = $this->entityManager->getClassMetadata(get_class($historyEntity));
$this->entityManager->getUnitOfWork()->computeChangeSet($classMeta, $historyEntity);
Profit
Hope this helps somebody!
I'd like to know how to access the Request object in an entity (Symfony2) to modify the user locale.
If someone has found a solution for my problem, please let me know.
It's not possible. This is by design: the entity is just a simple object that should know nothing about the request - it's the responsibility of the controller to interpret the request, and manipulate the entity based on that.
Something like:
//inside your controller:
public function fooBarAction(Request $request)
{
$entity = // get entity
$entity->setLocale($request->getSession()->getLocale());
}
The above is just example code, it won't work if you just copy and paste it. It's just to demonstrate the general idea. The entity should just be a very simple object, who's only responsibility is to hold some data. It shouldn't know where the data is coming from - that keeps it flexible (if you want to set the locale based on something else, you only have to change your controller, not all your entities).
It is possible, but...
What you can but never should do is inject the Request object into the entity (Practically turning your entity into service, see here). Also, even worse idea (but which people still do), you could inject the whole container and get Request from there. The reason why you shouldn't do it is you never should have any code that deals with business rules or any system code in your entities.
You can switch your locale directly in your routes by using _locale custom variable (accessible also from the Request). Or you can create a kernel listener, which will do the required functionality for you. This way you keep your code testable and decoupled.
I'm having a design issue in my project, related to where put some business logic.
I have three entities, Event, TicketOrder and Ticket. One Event has a lot of TicketOrders and one TicketOrder has a lot of Tickets.
In my template, I have to show how many tickets an Event has. I've thinking of the best approach to achieve this and didn't get a good solution. I've tried this:
1) Create a private member 'ticketsCount' in Event entity, with setTicketsCount and getTicketsCount method. Create a 'loadTicketsCount' method with a LifeCycleCallback 'PostLoad', to access the TicketRepository method 'findByEvent'. This was impossible because I can't access repository in an entity class.
2) In the action that will be used to display the Event, I can access Ticket Repository and set event 'ticketsCount' property manually. I don't know if it is a good approach because if my action is listing a lot of events I'll have to loop trough all events and make a repository call to each of then.
I really don't know the best approach to achieve this and will really appreciate if someone can help me.
Thanks! ;)
When you use findAll, findBy or findBy* methods of doctrine entity repository, a simple php array is returned containing the entity objects.
The array class implements countable interface. So using twigs length filter
{{ ticketOrder.tickets|length }}
you perform a simple php count() on the array.
Actually it makes now sense to perform a count query, because you already have the result in memory. So it seems more efficient to count the result and retrieve it from memory, because when you access associations they are completely loaded into memory.
However associations between entities can get pretty large. So imagine you have associations with hundred thousands of entities. You won't those entites to be loaded all together and kept in memory all the time. So in Doctrine 2.1 you can annotate an association as Extra Lazy. If you do so in your case a count query is performed when you call the above twig filter. But the result is not kept in memory.
http://docs.doctrine-project.org/en/2.0.x/tutorials/extra-lazy-associations.html
According to your latest comment:
I can imagine one way to do this. In a template you can call a controller's action with the render statement like
{% render YourMainBundle:getTickets with { 'event_id' : event.id } %}
and in this action you can call a query that looks for all tickets associated to the certain event. This action has to return html, e.g. an template filled with data.