Service Controllers =================== As your Silex application grows, you may wish to begin organizing your controllers in a more formal fashion. Silex can use controller classes out of the box, but with a bit of work, your controllers can be created as services, giving you the full power of dependency injection and lazy loading. .. ::todo Link above to controller classes cookbook Why would I want to do this? ---------------------------- - Dependency Injection over Service Location Using this method, you can inject the actual dependencies required by your controller and gain total inversion of control, while still maintaining the lazy loading of your controllers and its dependencies. Because your dependencies are clearly defined, they are easily mocked, allowing you to test your controllers in isolation. - Framework Independence Using this method, your controllers start to become more independent of the framework you are using. Carefully crafted, your controllers will become reusable with multiple frameworks. By keeping careful control of your dependencies, your controllers could easily become compatible with Silex, Symfony (full stack) and Drupal, to name just a few. Parameters ---------- There are currently no parameters for the ``ServiceControllerServiceProvider``. Services -------- There are no extra services provided, the ``ServiceControllerServiceProvider`` simply extends the existing **resolver** service. Registering ----------- .. code-block:: php $app->register(new Silex\Provider\ServiceControllerServiceProvider()); Usage ----- In this slightly contrived example of a blog API, we're going to change the ``/posts.json`` route to use a controller, that is defined as a service. .. code-block:: php use Silex\Application; use Demo\Repository\PostRepository; $app = new Application(); $app['posts.repository'] = function() { return new PostRepository; }; $app->get('/posts.json', function() use ($app) { return $app->json($app['posts.repository']->findAll()); }); Rewriting your controller as a service is pretty simple, create a Plain Ol' PHP Object with your ``PostRepository`` as a dependency, along with an ``indexJsonAction`` method to handle the request. Although not shown in the example below, you can use type hinting and parameter naming to get the parameters you need, just like with standard Silex routes. If you are a TDD/BDD fan (and you should be), you may notice that this controller has well defined responsibilities and dependencies, and is easily tested/specced. You may also notice that the only external dependency is on ``Symfony\Component\HttpFoundation\JsonResponse``, meaning this controller could easily be used in a Symfony (full stack) application, or potentially with other applications or frameworks that know how to handle a `Symfony/HttpFoundation <http://symfony.com/doc/master/components/http_foundation/introduction.html>`_ ``Response`` object. .. code-block:: php namespace Demo\Controller; use Demo\Repository\PostRepository; use Symfony\Component\HttpFoundation\JsonResponse; class PostController { protected $repo; public function __construct(PostRepository $repo) { $this->repo = $repo; } public function indexJsonAction() { return new JsonResponse($this->repo->findAll()); } } And lastly, define your controller as a service in the application, along with your route. The syntax in the route definition is the name of the service, followed by a single colon (:), followed by the method name. .. code-block:: php $app['posts.controller'] = function() use ($app) { return new PostController($app['posts.repository']); }; $app->get('/posts.json', "posts.controller:indexJsonAction"); In addition to using classes for service controllers, you can define any callable as a service in the application to be used for a route. .. code-block:: php namespace Demo\Controller; use Demo\Repository\PostRepository; use Symfony\Component\HttpFoundation\JsonResponse; function postIndexJson(PostRepository $repo) { return function() use ($repo) { return new JsonResponse($repo->findAll()); }; } And when defining your route, the code would look like the following: .. code-block:: php $app['posts.controller'] = function($app) { return Demo\Controller\postIndexJson($app['posts.repository']); }; $app->get('/posts.json', 'posts.controller');