I read the article yesterday: https://igor.io/2012/11/09/scaling-silex.html
And another one http://davedevelopment.co.uk/2012/10/03/Silex-Controllers-As-Services.html
So a conceptual question rised in my head:
Currently I do have a lot of controllers in separate classes. I overwrite controller_resolver
to create a controller class instance and inject $app
into contoller's constructor.
I define routes like this $app->get('/hello', 'HelloController::indexAction')
<- my controller resolver will create new HelloController($app);
- so far so good.
But to be honest it became a ServiceLocator pattern, not a DependencyInjection, because I do inject whe whole $app
which looks like ServiceLocator usage.
Now I am in doubt: should I leave it as is (because it works well) or try "controllers as services" to inject only those sevices on which my controller really depends on? May be my SeviceLocator approach will hit me some day? (people say that DI is better for tests).
I have also looked into Symfony Framework Bundle: class Controller
extends abstract class ContainerAware
which also have the whole $container
injected! ServiceLocator approach in full stack framework?
Any recomendation? Pros/cons?
The framework uses the Dependency Injection pattern and not the Service Locator pattern.
All controllers aren't services by default. The ContainerAware
class includes methods to get access to the service container, so you can call Services inside the Controller.
If you are going to use a Controller as a Service you need to remove the Controller
extend. All dependencies you want to use inside the controller needs to be injected by the Service Container.
Read more about this in a blogpost by richard miller, one of the core contributors of Symfony2.
The Silex micro-framework provides the bare bones of a framework, it's up to you how the architecture looks and which patterns you use.
The Silex documentation uses Controllers that aren't Services. It injects the complete Service Container inside very Controller:
$app->post('/post/{id}-{slug}', function($id, $slug) use ($app) {
// ...
});
If you want to use controllers as service, you should only inject the services you want to use inside the controller.
EDIT: The Controller::action
syntax refers also to a Controller that isn't a Service. The Controller:action
notation is used to refer to Controllers as Services.
There's lot's of personal preference involved here. What you've done already is a good (enough) step to organising your code base. Some people like myself take things a step further and move our controllers to the container, rather than injecting it in to some kind of BaseController. This happens in both Silex and the full stack Symfony framework.
My advice would be to leave everything you have as is, then try defining your next controller as a service, by practising BDD.
For example, the behaviour of a UserController view action:
Not once does it mention retrieving the database or the template renderer from a container. I'm comfortable not injecting the container, so I'll only inject what I'm led to believe I need by BDD.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With