Silex - InvalidArgumentException in ControllerResolver

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.

enter image description here

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

Answers (1)

Adam Cameron
Adam Cameron

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

Related Questions