How to fix RuntimeException for MW with RouteCollectorProxy

The index.php of my app like this:

<?php

declare(strict_types=1);

use Slim\Factory\AppFactory;
use DI\ContainerBuilder;

use App\Middleware\AddJsonResponseHeader;

use App\Controllers\CreateRasterController;
use App\Middleware\CreateRasterMiddleWare2;

use Psr\Http\Message\ResponseInterface;
use Slim\Handlers\Strategies\RequestResponse;
use Slim\Handlers\Strategies\RequestResponseArgs;

use Slim\Routing\RouteCollectorProxy;

define('APP_ROOT', dirname(__DIR__));

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

$container = null;
try {
    $builder = new ContainerBuilder;
    $container = $builder->addDefinitions(APP_ROOT . '/config/definitions.php')->build();
} catch (Exception $e) {
    return $e;
}

AppFactory::setContainer($container);

$app = AppFactory::create();

$collector = $app->getRouteCollector();
$collector->setDefaultInvocationStrategy(new RequestResponseArgs());

$app->addBodyParsingMiddleware();

$error_middleware = $app->addErrorMiddleware(true, true, true);

$error_handle = $error_middleware->getDefaultErrorHandler();
$error_handle->forceContentType('application/json');

$app->add(new AddJsonResponseHeader());

$app->add(ResponseInterface::class);

The route group, with MW

$app->group('/api/v1/create', function (RouteCollectorProxy $group) {
    $group->post("/rasters", CreateRasterController::class)->add(CreateRasterMiddleWare2::class);
    $group->post("/avatar", CreateRasterController::class . ':uploadAvatar');
});

The router MW

<?php

declare(strict_types=1);

namespace App\Middleware;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Psr\Http\Message\ResponseInterface as Response;

use Slim\Exception\HttpMethodNotAllowedException;
use Valitron\Validator;

class CreateRasterMiddleWare2
{
    private static Request $request;
    private static Response $response;

    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        self::$request = $request;
        self::$response = $handler->handle($request);

        //$this->processingBodyParameters();
        self::$response->getBody()->write(1234567890);
        return self::$response;
    }
}

And when I trying to call my api resource, I got an error:

[Sun Apr 28 07:17:59 2024] [::1]:2025 [500]: POST / - Uncaught RuntimeException: Callable Psr\Http\Message\ResponseInterface does not exist in D:\*.edu\rasters-service\vendor\slim\slim\Slim\CallableResolver.php:138
Stack trace:
#0 D:\*.edu\rasters-service\vendor\slim\slim\Slim\CallableResolver.php(90): Slim\CallableResolver->resolveSlimNotation()
#1 D:\*.edu\rasters-service\vendor\slim\slim\Slim\CallableResolver.php(71): Slim\CallableResolver->resolveByPredicate()
#2 D:\*.edu\rasters-service\vendor\slim\slim\Slim\MiddlewareDispatcher.php(167): Slim\CallableResolver->resolveMiddleware()
#3 D:\*.edu\rasters-service\public\index.php(53): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()
#4 D:\*.edu\rasters-service\vendor\slim\slim\Slim\MiddlewareDispatcher.php(269): Closure->{closure}()
#5 D:\*.edu\rasters-service\vendor\slim\slim\Slim\MiddlewareDispatcher.php(65): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()
#6 D:\*.edu\rasters-service\vendor\slim\slim\Slim\App.php(199): Slim\MiddlewareDispatcher->handle()
#7 D:\*.edu\rasters-service\vendor\slim\slim\Slim\App.php(183): Slim\App->handle()
#8 D:\*.edu\rasters-service\public\index.php(102): Slim\App->run()
#9 {main}
  thrown in D:\*.edu\rasters-service\vendor\slim\slim\Slim\CallableResolver.php on line 138
[Sun Apr 28 07:17:59 2024] [::1]:2025 Closing

So I’m discouraged, because not understand how it should work :\ Pls, help me with it.
P.S. I not sure that I fully understand how AppFactory, ContainerBuilder, DI and RouteCollectorProxy works. I’m newbie in this framework…

In your index.php two last lines look uncanny:

...
$app->add(new AddJsonResponseHeader());

$app->add(ResponseInterface::class);

certainly the last one.

Look at accepted method parameters:

    /**
     * @param MiddlewareInterface|string|callable $middleware
     */
    public function add($middleware): self
    {
        $this->middlewareDispatcher->add($middleware);
        return $this;
    }

ResponseInterface does not indicate anything related to middleware, and that is the point, because further on:

    /**
     * Add a new middleware to the stack
     *
     * Middleware are organized as a stack. That means middleware
     * that have been added before will be executed after the newly
     * added one (last in, first out).
     *
     * @param MiddlewareInterface|string|callable $middleware
     */
    public function add($middleware): MiddlewareDispatcherInterface
    {
        if ($middleware instanceof MiddlewareInterface) {
            return $this->addMiddleware($middleware);
        }

        if (is_string($middleware)) {
            return $this->addDeferred($middleware);
        }

        if (is_callable($middleware)) {
            return $this->addCallable($middleware);
        }

        /** @phpstan-ignore-next-line */
        throw new RuntimeException(
            'A middleware must be an object/class name referencing an implementation of ' .
            'MiddlewareInterface or a callable with a matching signature.'
        );
    }

each of three methods is supposed to return MiddlewareInterface, so if your dependency container does not include (and I bet it does not) any entry key ResponseInterface::class => ... returning an instance of MiddlewareInterface, the you’ve got a problem.

1 Like

Uncaught RuntimeException: Callable Psr\Http\Message\ResponseInterface does not exist

The method $app->add(…) is supposed to add a middleware, but the ResponseInterface is not a middleware, it is just a response object. So try to remove this line:

$app->add(ResponseInterface::class);

1 Like