Skip to content

Instantly share code, notes, and snippets.

@kix
Created October 16, 2012 04:29
Show Gist options
  • Save kix/3897241 to your computer and use it in GitHub Desktop.
Save kix/3897241 to your computer and use it in GitHub Desktop.
How to use controllers like in Symfony2 framework

How to use controllers like in Symfony2 framework

In Silex, the most common way to define the controller of a route is with a closure. But when your project gets bigger, you want to organize your code in classes. You can use the syntax ClassName::methodName in your route definition instead of a function () { ... } but you have to inject the Silex\Application $app as a parameter on each method of your controller class, which can become quite boring.

In order to avoid these repetitive injections, you need to create your own ControllerResolver which extends the Silex\ControllerResolver (inspired by the one in the Symfony2 framework bundle) :

namespace MyProject\Controller;

use Silex\ControllerResolver as SilexControllerResolver;

class ControllerResolver extends SilexControllerResolver
{
    /**
     * Returns a callable for the given controller.
     *
     * @param string $controller A Controller string
     *
     * @return mixed A PHP callable
     */
    protected function createController($controller)
    {
        if (false === strpos($controller, '::')) {
            throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
        }

        list($class, $method) = explode('::', $controller, 2);

        if (!class_exists($class)) {
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
        }

        $controller = new $class();
        if ($controller instanceof AbstractController) {
            $controller->setContainer($this->app);
        }

        return array($controller, $method);
    }
}

The code is pretty straightforward : you create a new $class() and if it is an instance of AbstractController you inject the Silex Application.

Now the AbstractController is easy to create :

namespace MyProject\Controller;

use Silex\Application;

abstract class AbstractController
{
    /**
     * @var Application;
     */
    protected $app = null;

    /**
     * @param Application $app
     */
    public function setContainer(Application $app)
    {
        $this->app = $app;
    }
}

Finally, you replace the Silex\ControllerResolver by your own in your bootstrap file :

$app['resolver'] = $app->share(function () use ($app) {
    return new \MyProject\ControllerResolver($app);
});

And that's all. You only have to make all your controller's class extend AbstractController.

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