Organizing Business Logic in Symfony2
I am converting Symfony1 application to Symfony2 and I try to follow Symfony2 best practices.
I have a problem with business logic: in the old application, all the logic was in the controller (very fat controllers). I've moved it to the entity repository, but I'm not sure if this is the correct way (because, among other things, I need to send emails and it doesn't work).
For example, the save function for the resource reservation manager (calendar):
- Start transaction
- Please confirm that the given resource is not being used for the period of time that I am trying to save
- If the data is correct and the resource is marked as "Required Confirmation", an email is sent to all users in the "Confirmation" group.
- An email is sent to the current user informing him that the resource has been reserved correctly (and, if necessary, advising that the "endorser" must confirm his reservation).
- If everything works well, complete the transaction. If an error occurs, rollback the transaction
As you can see, there is a lot of business logic (this example is one of the simplest modules) using multiple types of entities, users, mail senders, etc. So how can I organize it? Should I push the business logic into an object repository or is it better to use services? And for emails, maybe it's better to send them from an event listener? And do you know where I can find some examples?
source to share
Just run services for these tasks. For example; create a service that you can reuse, that you can test, to send email. Make the API as simple as possible and then you can use it in your controller.
The way I think about it is that the controller is ONLY there to send information around the various services and handle what is displayed to the user. Everything else should be monitored through the services and the responses from those services.
It's not bad to have small classes - your classes should strive to do one thing and one thing well. If you strip them out enough, they'll be easy to test and easy to reuse.
Symfony books are great resources for this kind of thing:
source to share
You may find this article by Martin Fowler helpful. He says & hellip;
In general, the more you find in the services, the more likely you are to rob yourself of the benefits of the domain model. If all your logic is in services, you have left yourself blind.
I suspect that he and Eric Evans will implement your business logic using a & hellip; style DDD approach;
class Resource { public function isUsedIn (TimePeriod $ tp); public function isMandatoryConfirmation (); } class ReservationManager { public function save (Resource $ r, TimePeriod $ tp) { if (! $ r-> isUsedIn ($ tp) || $ r-> isMandatoryConfirmation ()) { // send email to all the users from the "confirmers" group // send email to the current user } } }
Unfortunately, in my experience with Symfony2, this was not done and the code ended up inside the services. Symfony confirms that business logic can be put into Doctrine objects, but from my point of view this is a bit of an endearing proposal.
Services are containers and, as such, can easily access other services to perform other functions such as sending email, logging messages. Doctrine records cannot access other services, which means that, like Seer, we end up using services in our project.
If you like the idea of diverting more of your business away from services, it's not hard, however Doctrine and Symfony don't seem to support it out of the box :-(
source to share