slimphp / Slim

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
http://slimframework.com
MIT License
11.98k stars 1.95k forks source link

Invokable class unusable as route callback #1469

Closed designermonkey closed 9 years ago

designermonkey commented 9 years ago

Using the following (not pretty I know)

<?php

require __DIR__ . '/../vendor/autoload.php';

$app = new Slim\App();

class Test
{
    public function __invoke()
    {
        return 'test';
    }
}

$app->get('/', Test::class);

$app->run();

And after reading @silentworks article here, and with my own expectations that an invokable object should just be invoked, this is the result I get:

Slim Application Error
The application could not run because of the following error:

Details

Type: RuntimeException
Message: Test is not resolvable
File: /data/sites/local/vendor/slim/slim/Slim/CallableResolver.php
Line: 94
Trace

#0 /data/sites/local/vendor/slim/slim/Slim/CallableResolver.php(107): Slim\CallableResolver->resolve()
#1 /data/sites/local/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php(41): Slim\CallableResolver->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#2 /data/sites/local/vendor/slim/slim/Slim/Route.php(314): Slim\Handlers\Strategies\RequestResponse->__invoke(Object(Slim\CallableResolver), Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#3 /data/sites/local/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(114): Slim\Route->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#4 /data/sites/local/vendor/slim/slim/Slim/Route.php(288): Slim\Route->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#5 /data/sites/local/vendor/slim/slim/Slim/App.php(392): Slim\Route->run(Object(Slim\Http\Request), Object(Slim\Http\Response))
#6 /data/sites/local/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(114): Slim\App->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#7 /data/sites/local/vendor/slim/slim/Slim/App.php(304): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#8 /data/sites/local/public/index.php(32): Slim\App->run()
#9 {main}

The reason we are able to just call the Action Class name here is that Slim 3 will check for the __invoke method.

Sadly @silentworks this isn't right, although I agree with you it should be.

designermonkey commented 9 years ago

To get this to work, I have to manually create an instance of every callback class, which goes against the point of making this all accept string references to classes and methods.

$app->get('/', new Test);

or tell it to look for the invoke method:

$app->get('/', Test::class . ':__invoke');

All this seems a little odd. Could the CallableResolver be updated to allow the use of invokable classes?

designermonkey commented 9 years ago

Pretty embarrassed here, I looked at the code in the repo here and it has been changed since my local copy. Updated and it all works fine.

Sorry chaps.

designermonkey commented 8 years ago

I don't technically want to reopen this, but I still don't understand how Slim verifies that a class is invokable. It seems to me to just assume it is right at the end of the if/else block in the CallableResolver?

https://github.com/slimphp/Slim/blob/3.x/Slim/CallableResolver.php#L76

akrabat commented 8 years ago

Line 73 ensures that $class can be autoloaded and so line 76 instantiates it.

Line 81 checks that it is invokable.

designermonkey commented 8 years ago

Why am I so blind recently? Thanks.