Skip to content

Instantly share code, notes, and snippets.

@igorw
Created June 28, 2011 11:42
Show Gist options
  • Save igorw/1050974 to your computer and use it in GitHub Desktop.
Save igorw/1050974 to your computer and use it in GitHub Desktop.
Controllers as services with Silex.
<?php
class LazyServiceController
{
private $container;
private $serviceName;
public function __construct(\Pimple $container, $serviceName)
{
$this->container = $container;
$this->serviceName = $serviceName;
}
public function __invoke()
{
call_user_func($this->container[$this->serviceName], func_get_args());
}
}
class MyController
{
private $someService;
public function __construct(SomeService $someService)
{
$this->someService = $someService;
}
public function __invoke($name)
{
return $this->someService->translateName($name);
}
}
$app = new Silex\Application();
$app['some_service'] = function () {
return new SomeService();
};
$app['my_controller'] = function ($app) {
return new MyController($app['some_service']);
};
$app->get('/{name}', new LazyServiceController($app, 'my_controller'));
@till
Copy link

till commented Jun 30, 2011

What's the idea here? I mean. Why would I wrap a controller into a service?

@igorw
Copy link
Author

igorw commented Jun 30, 2011

Good question. :)

Well, the point of doing this in general is not having to inject the DI container into your controllers (instead, you inject the dependencies into the controller directly). Thus the controller no longer depends on the container.

Good: You get added flexibility. You no longer hard-code which services to use into your controller. You can specify that in the DI configuration instead. Example: You inject a UserProvider into the UserController for /profile, but inject a FacebookUserProvider into the same UserController for /profile/facebook.

Bad: You must manually configure your dependencies in the DIC config. You need to manually assign the injected dependencies. Optional dependencies are no longer lazy-loaded.

Now, I don't really think it makes sense to do this with Silex. Silex is a micro-framework, always injecting the container is perfectly acceptable. If you want code that is decoupled, extract that into a separate library and integrate it with your app using autoloading and pimple.

This was basically just a proof of concept to show how it could be done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment