Slim 3 DI Bridge and Middleware


#1

Hi,

I’m trying to add middleware to a route. It must redirect when $_SESSION[‘user_id’] not found.

Its something to do with the constructor… not sure how to pass the view or router detail to the middleware class

Error Im getting: Uncaught ArgumentCountError: Too few arguments to function App\Middleware\RedirectAuth::__construct(), 0 passed in /var/www/woods.local/app/routes.php on line 7 and exactly 1 expected in /var/www/woods.local/app/Middleware/RedirectAuth.php on line 14

Thanks

Bootstrap.php

require __DIR__ . '/../vendor/autoload.php';
$app = new \App\MyApp;              // class MyApp extends \DI\Bridge\Slim\App
require 'routes.php';

MyApp.php

namespace App;

use DI\ContainerBuilder;
use Interop\Container\ContainerInterface;
use Slim\Interfaces\RouterInterface;

class MyApp extends \DI\Bridge\Slim\App {

    protected function configureContainer(ContainerBuilder $builder) {
        $definitions = [
            \Slim\Views\Twig::class => function (ContainerInterface $container) {
                $view = new \Slim\Views\Twig(__DIR__ . '/../resources/views', [
                    'cache' => false,
                ]);

                $view->addExtension(new \Slim\Views\TwigExtension(
                        $container->get('router'), $container->get('request')->getUri()
                ));

                return $view;
            },
            \Slim\Interfaces\RouterInterface::class => function (ContainerInterface $container) {
                return new \Slim\Interfaces\RouterInterface;
            },
        ];

        $builder->addDefinitions($definitions);
    }

}

routes.php

namespace App\Middleware;
use Interop\Container\ContainerInterface;
use DI\ContainerBuilder;
use DI\Bridge\Slim\App;

$app->get('/', ['\App\Controllers\HomeController', 'index'])->add(new RedirectAuth());
$app->get('/register', ['\App\Controllers\RegisterController', 'index'])->setName('register');

RedirectAuth.php

namespace App\Middleware;

use App\Interfaces\ViewInterface as Twig;
use Slim\Interfaces\RouterInterface as Router;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class RedirectAuth {

    protected $router;

    public function __construct(Router $router) {
        $this->router = $router;
    }

    public function __invoke($request, $response, $next) {

        if (!isset($_SESSION['user_id'])) {
            return $response->withRedirect($this->router->pathFor('home'));
        }

        return $next($request, $response);
    }

}

#2

A couple of things I see, but note I haven’t actually tried running your code. $router should probably be an instance of Slim\Router instead of Slim\Interfaces\RouterInterface.

use Slim\Router;

And then you can likely remove the \Slim\Interfaces\RouterInterface::class entry from your container. Since you are type hinting it into the RedirectAuth it should know where to find it.

Finally, in routes.php you can probably just use ->add('App\Middleware\RedirectAuth') so that PHP-DI can do its magic.


#3

Thanks Tim you nailed it.


#4

I love it when that happens. :slight_smile: