phpslim

Slim Framework Is Giving A Confuing Uncaught TypeError


I've just installed a fresh copy of slim via composer with my own setup. Very simple index.php with very little in it:

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require_once __DIR__ . '/../bootstrap.php';

// start the app
$APP = AppFactory::create();

/**
 * Middleware to check validation before any routes
 */
$APP->add(function(Request $request, Response $response, callable $next){

    $response = $next($request,$response);

    return $response;

});

/**
 * Add routes
 */
$APP->get('/test',function(Request $request, Response $response, array $args){

    return $response->getBody()->write('hello');
});


// run the app
$APP->run();

Php is giving a very strange error:

**Fatal error: Uncaught TypeError: Argument 2 passed to {closure}() must be an instance of Psr\Http\Message\ResponseInterface, instance of Slim\Routing\RouteRunner given, called in /var/www/vendor/slim/slim/Slim/MiddlewareDispatcher.php on line 275 and defined in /var/www/public/index.php:16 Stack trace: #0 /var/www/vendor/slim/slim/Slim/MiddlewareDispatcher.php(275): {closure}(Object(Slim\Psr7\Request), Object(Slim\Routing\RouteRunner))

1 /var/www/vendor/slim/slim/Slim/MiddlewareDispatcher.php(73): class@anonymous->handle(Object(Slim\Psr7\Request)) #2

/var/www/vendor/slim/slim/Slim/App.php(206): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request)) #3 /var/www/vendor/slim/slim/Slim/App.php(190): Slim\App->handle(Object(Slim\Psr7\Request)) #4 /var/www/public/index.php(34): Slim\App->run() #5 {main} thrown in /var/www/public/index.php on line 16**

I can't work out why it's saying the basic middleware here is taking an instance of Slim\Routing\RouteRunner when I'm clearly giving it Psr\Http\Message\ResponseInterface

Any idea?

EDIT:

Thanks to the answer from delboy, but can you be more specific please? The slim documentation shows to use it like this (http://www.slimframework.com/docs/v3/concepts/middleware.html):

$app->add(function ($request, $response, $next) {
    $response->getBody()->write('BEFORE');
    $response = $next($request, $response);
    $response->getBody()->write('AFTER');

    return $response;
});

But this doesn't work! Always get the type error, so is their documentation out of date? If so, how do I implement the middleware here?

This example code they give also produces another weird error:

Fatal error: Uncaught ArgumentCountError: Too few arguments to function {closure}(), 2 passed in /var/www/vendor/slim/slim/Slim/MiddlewareDispatcher.php on line 275 and exactly 3 expected in /var/www/public/index.php:26 Stack trace: #0 /var/www/vendor/slim/slim/Slim/MiddlewareDispatcher.php(275): {closure}(Object(Slim\Psr7\Request), Object(class@anonymous)) #1 /var/www/vendor/slim/slim/Slim/MiddlewareDispatcher.php(73): class@anonymous->handle(Object(Slim\Psr7\Request)) #2 /var/www/vendor/slim/slim/Slim/App.php(206): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request)) #3 /var/www/vendor/slim/slim/Slim/App.php(190): Slim\App->handle(Object(Slim\Psr7\Request)) #4 /var/www/public/index.php(38): Slim\App->run() #5 {main} thrown in /var/www/public/index.php on line 26

I the example code passes 3 params, not 2!

EDIT:

Ok, the Slim documents are clearly out of date, it should be done like this:

$app->add(function(ServerRequestInterface $request, RequestHandlerInterface $handler) {

    $response = new Response();
    $response->getBody()->write('STUFF');

    return $response;
});

Solution

  • Your middleware is not implementing PSR-15. You shouldn't pass a response, but a request handler interface:

    namespace Psr\Http\Server;
    
    use Psr\Http\Message\ResponseInterface;
    use Psr\Http\Message\ServerRequestInterface;
    
    /**
     * Participant in processing a server request and response.
     *
     * An HTTP middleware component participates in processing an HTTP message:
     * by acting on the request, generating the response, or forwarding the
     * request to a subsequent middleware and possibly acting on its response.
     */
    interface MiddlewareInterface
    {
        /**
         * Process an incoming server request.
         *
         * Processes an incoming server request in order to produce a response.
         * If unable to produce the response itself, it may delegate to the provided
         * request handler to do so.
         */
        public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface;
    }
    

    https://www.php-fig.org/psr/psr-15/