utils
utils copied to clipboard
Error when trying to use an object & method as a handler
I am trying to register a route with fast route using an Object and static method with the following code:
static public function registerRoute( RouteCollector &$r ): void {
$r->addRoute(['GET', 'OPTIONS'], '/password', array( self::class, 'renderChallenge') );
}
instead of the handler being called I instead get the following error message:
Argument 1 passed to Middlewares\Utils\CallableHandler::__construct() must be callable, object given, called in /src/vendor/middlewares/utils/src/RequestHandlerContainer.php on line 51
In the course of trying to debug I decided to test if what I was passing was callable using the following:
// Regular function to check if something is callable
function isThisCallable( callable $callable ) {
call_user_func( $callable );
}
// Modified code from above
static public function registerRoutes( RouteCollector &$r ): void {
$r->addRoute(['GET', 'OPTIONS'], '/password', function() {
isThisCallable( array(static::class, 'renderChallenge') );
} );
}
This test code ran as expected and called the static object's method. Is this a bug or is there another way I should be passing an object and method as the handler?
The CallableHandler
class is not receiving a callable element. Can I see the code including how are the middlewares implemented?
After doing some additional testing the only ways I have found to make a static method call are by setting the handler to __CLASS__."::loginRedirect_renderChallenge"
or invoking a new instance of the class, array( new self, "loginRedirect_renderChallenge" )
. In terms of a static method call via an array I have yet to find anything that works other than invoking a new instance of the class. I also did a quick check and replaced self::class
with the full name of the class array( 'namespace\Class', 'renderChallenge')
, but still got the same error.
Below is how the Middlewares are implemented
// Emitter for response
$middlewares[] = new Middlewares\Emitter();
// Redirect to https
$middlewares[] = ( new Middlewares\Https() )->includeSubdomains();
// remove www
$middlewares[] = new Middlewares\Www(false);
// Removes the trailing slash
$middlewares[] = new Middlewares\TrailingSlash(false);
// Save the client ip in the '_ip' attribute
$middlewares[] = (new Middlewares\ClientIp())
->attribute('_client-ip');
// Log the request
/** @var Monolog\Logger $logger */
$middlewares[] = (new Middlewares\AccessLog( $GLOBALS['AccessLogger'] ) )
->ipAttribute('_client-ip');
// Negotiate the language
$middlewares[] = new Middlewares\ContentLanguage([ 'en', 'gl', 'es' ]);
// Handle Error Responses
$middlewares[] = new Middlewares\ErrorResponse();
// Negotiate the content-type
$middlewares[] = new Middlewares\ContentType();
// CORS Analyzer
/** @var Neomerx\Cors\Analyzer $CORS_analyzer */
$middlewares[] = new Middlewares\Cors( $GLOBALS['CORS_analyzer'] );
// Insert the X-Uuid header of the request and response. Useful for debugging purposes.
$middlewares[] = new Middlewares\Uuid();
// Calculate the response time
$middlewares[] = new Middlewares\ResponseTime();
// Add cache expiration headers
$middlewares[] = new Middlewares\CachePrevention();
// Sets header to disable robots
$middlewares[] = new Middlewares\Robots(false);
//Parse the json payload
$middlewares[] = new Middlewares\JsonPayload();
//Parse the urlencoded payload
$middlewares[] = new Middlewares\UrlEncodePayload();
// Set the route via fast-route
/** @var FastRoute\Dispatcher\GroupCountBased $router */
$middlewares[] = new Middlewares\FastRoute( $GLOBALS['router'] );
//Calls the callable handler from FastRoute
$middlewares[] = new Middlewares\RequestHandler();
$response = ( new Middlewares\Utils\Dispatcher( $middlewares ) )
->dispatch( Zend\Diactoros\ServerRequestFactory::fromGlobals() );
This is the code of RequestHandler middleware that decided how to handle your callable: https://github.com/middlewares/request-handler/blob/master/src/RequestHandler.php#L75
If it's a string (your case now), seems to work fine.
If it's an array (like your previous case Array(static::class, 'renderChallenge')
) it enter here (https://github.com/middlewares/request-handler/blob/master/src/RequestHandler.php#L80) and try to get the class instance from the container. The class you're providing can be instantiated? or is static?
The class can be instantiated the method it is calling is static.
Ok, I'll take a look. Thanks