Pragmatism in the real world

Routing in Slim 4

Routing in Slim 4 works pretty much exactly the same as in Slim 3. They are used to map a URL that the browser requests to a specific handler that executes the code for that particular page or API endpoint. You can also attach middleware that will only be run when that route is matched.

The route in the slim4-starter looks like this:

$app->get('/[{name}]', HomePageHandler::class);

It is made up of the method, the pattern and the handler.

The method

Slim’s App object contains a number of helper methods for defining routes. The important ones are:

$app->get($pattern, $handler) For responding to an HTTP GET request
$app->post($pattern, $handler) For responding to an HTTP POST request
$app->put($pattern, $handler) For responding to an HTTP PUT request
$app->delete($pattern, $handler) For responding to an HTTP DELETE request
$app->map(['GET', 'POST'], $pattern, $handler) For responding to more than one HTTP method with the same handler

You can probably spot the naming convention!

The pattern

The $pattern parameter contains the path that you want to match. Internally, Slim uses FastRoute and the pattern syntax comes from there. This is a regex based system and has a number of ways to match:

Literal '/news' Matches the string as typed
Placeholder '/news/{id}' Use braces to create a placeholder that is a variable available to your handler
Placeholder pattern match '/news/article-{id:[0-9]+}' Only matches if the text for the placeholder matches the regular expression (digits only in this example)
Optional '/news[/{year}[/{month}]]' Use square brackets for optional segments. These can be nested.

The slim4-starter route’s pattern is ''/[{name}]'> This will match / and also any other string that does not contain a /, such as /rob.

The handler

The $handler parameter is the code that will be called when the route is matched. This can be any PHP callable or a string.

If it is a string, then it needs to be either the name of a class or the name of a key in your dependency injection container’s configuration. The class class should implement PSR-15’s RequestHandlerInterface though it can also be any class that implements __invoke().

If you are using a DIC, then Slim will try and retrieve your handler from it, so that you can ensure that any dependencies that the handler needs can be injected. If the DIC cannot provide the handler or you’re not using a DIC, then Slim will instantiate it directly.

The HomePageHandler class in slim4-starter is a PSR-15 RequestHandler and looks like this:

<?php

declare(strict_types=1);

namespace App\Handler;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;
use Slim\Psr7\Response;

class HomePageHandler implements RequestHandlerInterface
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $this->logger->info('Home page handler dispatched');

        $name = $request->getAttribute('name', 'world');
        $response = new Response();
        $response->getBody()->write("Hello $name");
        return $response;
    }
}

In this case the handle() method is called by Slim and we must return a PSR-7 Response. We’re using a dependency injection container (PHP-DI) and it injects a logger into our handler so that we can log what we’re doing when we handle a request.

The route object

When you add a route to Slim, a route object is returned. There’s a few useful things you can do with it.

Firstly you can set a name for the route:

$route = $app->get('/[{name}]', HomePageHandler::class);
$route->setName('home');

If a route has a name, you can use it to generate the path:

$url = $app->getRouteCollector()->getRouteParser()->urlFor('home);

This is particularly useful when building web sites using Twig-View (in beta for Slim 4).

Another thing you can do with a route object is add middleware to it:

$route->addMiddleware(SomePsr15Middleware::class);

The SomePsr15Middleware class is a PSR-15 Middleware and is only run if the route is matched. It will run after the middleware added directly to $app and before the route handler.

That’s it

That’s all there is to setting up routes in Slim 4. To understand it more, create a quick project using the slim4-starter and have a play!

3 thoughts on “Routing in Slim 4

Comments are closed.