Access service container out of entities

New topics about Symfony 2 should go here

Moderators: tiagojsag, dcobalt

Access service container out of entities

Postby micham42 » Thu Nov 22, 2012 7:20 pm

Hello,

i`ve been playing with symfony a few weeks now. its great. most of the approaches are really nice. But i have some headache with doctrine entities and the access of the service container. Out of the box the DI-Container cant be accessed by entities. I`ve googled a lot and read some discussions. everyone say, it should not be necassary to access the container out of entities. i dont understand this. I like the idea of feature reach models. for example, within a user-model it would be nice to send an registration email like $user->sendRegistrationEmail() or $user->setRandomPass() or something else... maybe i want to do a native sql query (we are using heavily database...)

I know, that i could implement ContainerAware and inject the container. But that looks a bit unbeautiful. I`ve read a lot of times "rethink your model", but i didnt read why? And whats the best practise for the examples above?

greets

Michael
micham42
Junior Member
 
Posts: 2
Joined: Thu Nov 22, 2012 7:10 pm

Re: Access service container out of entities

Postby tiagojsag » Thu Nov 22, 2012 7:49 pm

Hi,

Indeed, if you need service container inside your entities, you need to rethink the way you are doing things. It's MVC, and you should keep M and C separated.

Regarding the examples you ask for, typically you send an email to a user or set it's password when someone does something (even if someone is a cron job). User actions are handled by controllers. So instead of $user->sendRegistrationEmail() in your user entity, you should have, in your controller, a $this->sendRegistrationEmail($user). If you wanna do it really by the book, $this->get('my.email.service')->sendRegistrationEmail($user) is the way to go. More info on the advantages of service injection on the symfony docs.

By now you're asking: "yes, but why shouldn't I just make my entities implement ContainerAware?". Well, technically, you can. It's just a bad practice, as it will probably make you entity classes huge, hard to maintain, prone to bugs. And it's not the true symfony way of doing things, which will also mean you'll get problems down the road, and google and this forum won't be able to help you that much, as everybody else is doing it differently.

hope this helps

cheers
Tiago Garcia
@tiagojsag

Core Web Developer @ Shopware
http://www.shopware.de
User avatar
tiagojsag
Faithful Member
 
Posts: 885
Joined: Wed Aug 10, 2011 4:58 pm

Re: Access service container out of entities

Postby dcobalt » Thu Nov 22, 2012 9:20 pm

Yeah, services are the way to go.

Also, keep your controller code small. Don't create a "sendRegistrationEmail" method in a controller. Put that in a service, and call the service from a controller.
As a general rule, any business logic that is getting relatively complex in a controller, you should abstract out into a service. That way, your controller code stays small, and you can call those business logic services from anywhere, reusing a lot of code.
There's also listeners, which are neat for firing off an action when a new entity is persisted or an entity is updated. For example, in my project I have a Notification listener which calls a mailer service after a Notification entity is persisted.
dcobalt
Faithful Member
 
Posts: 283
Joined: Thu Oct 20, 2011 6:06 pm

Re: Access service container out of entities

Postby micham42 » Fri Nov 23, 2012 11:21 am

its hard to believe that thats the way to go. in my view it shouldnt matter, wether a specific "task" needs only the own data or it requires some external services. for example:

doctrine shows in the documentation / tutorial a BankAccount Entity, that has a getBalance() method:

Code: Select all
$account = new BankAccount();
$account->getBalance();


that method calculates the balance by the entries, that the account has (by iterating over it). in that case, the getBalance() method would be okay. well, take a modification of the example: instead of iterating over the entries, the balance will be retrieved by a Rest-Service. In that case, the getBalance has to move out of the model... i dont like it.

so, finally that my arguments against the service-approach:

    - models / entities should keep the business logic. sending an email, or retrieving data from a rest-service is in my view business logic
    - the caller / user of the model shouldnt matter, what the model does in the background (how the logic works)
    - its more simple to understand the business-logic, when its central.
micham42
Junior Member
 
Posts: 2
Joined: Thu Nov 22, 2012 7:10 pm

Re: Access service container out of entities

Postby tiagojsag » Fri Nov 23, 2012 11:59 am

Doctrine is project on it's own. Symfony sits on top of it. If you go that way, we can also say that Doctrine sits on top of MySql, and we can just write raw queries and forget about the ORM. You definitely can, which doesn't mean you should ;)

Regarding your arguments and ours, I'm sure we could all be here until Christmas discussing the pros and cons of choosing either approach is, as both have them. We are not saying that your approach is without virtue, and ours without flaw. Like I told you before, this is the recommended way to do things, and I'm sure that people back at Sensio Labs HQ gave it a lot of thought before saying stuff should be done like this. If you really feel uncomfortable using service injection and/in controllers to do your logic, go ahead and inject services in your entities. It's just not the recommended way, and thus has the implications I mentioned before, but, in theory, it should work.

cheers
Tiago Garcia
@tiagojsag

Core Web Developer @ Shopware
http://www.shopware.de
User avatar
tiagojsag
Faithful Member
 
Posts: 885
Joined: Wed Aug 10, 2011 4:58 pm


Return to General Symfony 2 discussion

Who is online

Users browsing this forum: No registered users and 5 guests