Reputation: 41
Hi. I'm new to Silex (2.0), and I'm trying to pass the $app variable to my Controller, so I'm trying to create my Controller as a service.
I am following the documentation guide, but when registering my Controller I get an error of the type: InvalidArgumentException: Class "controller. default" does not exist.
On my index.php:
$app->register(new Silex\Provider\ServiceControllerServiceProvider());
// Register controller as services.
$app['controller.default'] = function() use ($app) {
return new Fortunio\Controller\DefaultController($app);
};
$app->get('/', "controller.default::indexAction");
If I change the last line of code, the application runs smoothly and the error disappears:
$app->get('/', 'Fortunio\Controller\DefaultController::indexAction');
On my Controller:
<?php
namespace Fortunio\Controller;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
class DefaultController
{
public function indexAction(Application $app, Request $request)
{
// my controller code here
}
}
Where's my mistake?
Thank you in advance.
Upvotes: 2
Views: 95
Reputation: 29870
Firstly: nicely put-together question.
As far as I can see yer following the docs, so if they claim that should work: your code should work. That said, this is not the approach we take with using controllers as services. Our approach is more like this:
class ControllerProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$app['controller.thing'] = function ($app) {
return new ThingController();
};
}
}
class RouteProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$app->get('/thing/{id}/', function (Request $request) use ($app) {
return $app['controller.thing']->doGET($request);
})->assert('id', '\d+');
}
}
use Silex\Application as SilexApplication;
class Application extends SilexApplication
{
public function __construct()
{
$this->register(new ControllerProvider());
$this->register(new RouteProvider());
}
}
$app = new Application();
The key difference is this bit, in the RouteProvider:
$app->get('/thing/{id}/', function (Request $request) use ($app) {
return $app['controller.thing']->doGET($request);
})->assert('id', '\d+');
See we don't use the string reference to the controller service (ie: just controller.thing:doGET
), we use the actual reference to the controller in the DI container, and actually call the method in the closure.
I want to check if they docs version actually works, but I need to get back to my day job. I'll have a fiddle with it later on and come back with findings as to whether I get it working or not. I def have had the controller.thing:doGET
approach working in the past, but even then my approach (using Silex 1.x) was slightly different. It's in a blog article here: PHP: Silex Controller Providers, but I would not recommend that approach any more. I include it just to demonstrate that that syntax can be made to work.
Upvotes: 1