Symfony event vs service - symfony

Hi I have a question about symfony application architecture,
In my application I create different user, but when a user is created, updated, deleted, or his picture change, I need to do some action.
What is the best way to do this ? I excluded to do this on a controller action. There is 2 others solutions :
Create differents events like user.created, user.updated, ... And dispatch it on the controller action and make different listener to do the different action like MailListener (for user.created) TaskListener (for user.created) for add a task.
Use a service like UserManager and on this service have a method like userCreated() and on this method call differents actions like sendMailOnCreated, addTaskOnCreated for example.
For you what is the best method ?

For me, your first solution is the best one. It's clearly a use case for the Event component. It will be easier to maintain and more readable.
Moreover, if you need to add more listener you just need to create another one and bind it to your event. You don't need to modify your controller anymore.

Related

how do I access ViewModel inside Work Manager

I'm trying to access ViewModel using hilt inside the worker class which I created but unable to do so, can anyone help please?
You should not try do such a thing in no way. They have totally different lifecycle and one is UI related - the other is not. You should create some other object, like a Singleton, and use it to share the data between the ViewModel and the Work. You can pull the data or use Observer pattern. VM has onCleared method so you can unregister there if you use Observer and observe the data from the VM in the Singleton.

How to test that EventListener has been called on event in Symfony?

What I have:
I have an EventListener that listens to PreRemove entity event in Symfony.
services:
my_bundle.entity_listener.my_listener:
class: 'MyCompany\MyBundle\MyListener'
public: false
tags:
- { name: doctrine.orm.entity_listener, entity: 'MyCompany\MyBundle\Entity\MyEntity', event: preRemove }
What I want:
I want to have a test (functional/integrational/unit or any other really) that somehow checks that when MyEntity is being removed a particular EventListener is being called.
UPDATE
I don't want to do it in a unit test, the need is to actually check that event dispatcher will really call that particular event listener to that particular event.
UPDATE 2
I thought it was obvious, but it seems that it's not - the solution should NOT modify EventListener or Event.
UPDATE 3
I specified that I do not care what the name of the test is: functional, unit or any other.
UPDATE 4
The solution must guarantee that test will pass in context of any environment. So, if someone extends my bundles and messes with my definitions I should still be able to validate if the EventHandling actually works.
Also, checking the result of handling is not an option because:
EventListener can do absolutely anything - there may be cases where I cannot simply check the result and know for sure that EventListener works.
Someone may handle an Event in almost exactly the same way, so that the "result" is the same, but the "way" is wrong.
A functional test is for testing functionality; it isn't intended to test the implementation of that functionality or the configuration of that implementation.
A test such as the one you propose will be brittle and not very useful.
What you probably want is to test the feature that the event listener implements.
check out this : Write UnitTest for Symfony EventListener
It may be of help, as i had a (sort of) similar issue/question
How about creating a compiler pass and add it to the last stage of container compilation:
$container->addCompilerPass(
new CheckEntityListenerRegistered(),
PassConfig::TYPE_AFTER_REMOVING,
-1000
);
That compiler would get executed last. You could check from that point if your listener is registered properly, and if it is, you could assume it's going to be executed by the Doctrine's Unit of Work.
I think I understand what you want. You want a integration test (to test it on all environment) without modifying the listener, the event dispatcher, etc.
Solution 1
When you work on dev, test or prod symfony load different events dispatchers it use the same interface and behaviour but it is different implementations (I haven't check doctrine one).
So you will have different dispatchers for each environment and you don't want to know what happens inside. Let's call this blackbox.
Action delete -> [ black box -> listener called ] -> listener effect
You don't want to look at the blackbox or touch it in any way? Search for the effect that has the listener on the system. Database, log file, mailer, etc.
Solution 2
If you allow me to hook into the blackbox you I will sorrounder the listener with a proxy and monitor if the listener has been called on the proxy.
Solution 3
Alternative you can use the data collectors from the symfony profiler but you won't probably have that enabled on production.
Maybe you can use the symfony profiler?
see How to Use the Profiler in a Functional Test
in the profiler events section you have two tabs with called / not called Listeners http://whatever.com/app_dev.php/_profiler/352211?panel=events

Limit access to the route

I'm new in symfony2 and I'm currently facing a problem. I would like to restrict the access on some of my page based on some dates contained in my database.
For example all the page after my mon.site/home/ would be redirect on an error page. I have already thinking on a event listener, but don't know how to restrict on some URL. Is there a better way to implement this function? If not how can I do it?
It's quite straightforward to me. You can choose between two different solutions
First solution
1) Create a custom event and event subscriber.
2) Dispatch event you've created at 1) everywhere (in every action) you need an extra control
3) Inside the event subscriber call for a method into custom event or directly a method of the subscriber to check if the "request satisfy your needs"
4) Raise an AccessDeniedException.
Second solution
1) With DependencyInjection create a custom configuration where you can specify what controller's actions should be checked for the condition you wish
2) Create an EventListener that listen for kernelRequest event
3) Into EventListener just check for condition
4) Raise an AccessDeniedException.
For restricting access you can use:
voters (and also using different strategies of access decision
manager)
you can also restrict access for whole sections of your app, using
access_control option in your security.yml
you can also use acl
try to avoid using listeners.
P.S. and also if this not enough you can configure .htaccess

Insert entity in preUpdate event

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!

Does Prism/Unity have a "service preloader"?

I've got a number of modules in a Prism application which load data that takes 3-8 seconds to get from a service.
I would like to be able to say in my bootstrapper something like this:
PSEUDO-CODE:
Customers allCustomers = Preloader(Models.GetAllCustomers);
And this would run in a background thread and when the user actually needs the variable "allCustomers" it would be fully loaded.
Is there an automatic service in Prism/Unity which does this type of preloading?
No, there is not.
However...
What you can consider is adding your ViewModel with a ContainerControlledLifetime to the container in your ConfigureContainer method that the views can use. You'd kickoff your threaded request in the constructor of your ViewModel and allow Views to pull this ViewModel out of the Container.
Even if they grab the ViewModel out of the container before the GetAllCustomers method is done firing, they will be notified correctly if the property you store the customers in implements INotifyPropertyChanged correctly.
If it was more appropriate, you could also do this from the Modules (in the Initialize method), rather than in the bootstrapper (for instance, if your Module was what actually knew about your Customer's Model).

Resources