A First Look at Slim 4

DZone 's Guide to

A First Look at Slim 4

Get started with Slim 4, a customizable php framework.

· Web Dev Zone ·
Free Resource

With Slim 4, we have continued the tradition of allowing you to use the framework in the way that best fits you and your project. You can create a Slim application entirely in a single file, suitable for prototyping through to a few files for a simple web hook or serverless action, all the way to a fully-decoupled application suitable for an enterprise.

From my point of view, the big changes with Slim 4 are:

  • Support for PSR-15 middleware.
  • Routing is now independent middleware, allowing middleware to run before and after routing.
  • Error handling is decoupled and optional.
  • No built-in DI container. Slim no longer ships with or depends on one to work.
  • No built-in PSR-7 implementation. Slim's own one is now in Slim-Psr7.
  • Less "surprise":
    • No automatic handling of _method POST field.
    • No automatic adding of a Content-Length header to the Response.
    • No automatic output buffering.

There are of course many other changes, but you'll notice that this release is all about flexibility. You should be able to bring your own DI container and PSR-7 implementation to the party, and you now have much easier control over how errors are handled and displayed. I also like that you can now have some middleware run before routing and some run after without having to use groups.

A Detailed Look at Creating an App

As you can imagine, this amount of flexibility means more setup, so there are some useful helpers. Before we look at those though, let's look at how to create a Slim 4 application instance the long way.

If you're in a hurry, feel free to jump to the recommended way below.

Constructing the App Instance

The constructor to Slim\App has this signature:

public function __construct(
        ResponseFactoryInterface $responseFactory,
        ?ContainerInterface $container = null,
        ?CallableResolverInterface $callableResolver = null,
        ?RouteCollectorInterface $routeCollector = null,
        ?RouteResolverInterface $routeResolver = null

You can see the flexibility most clearly here. When you create a new Slim\App, you need to set a PSR-17 response factory so that Slim can create a response object for you to return in your route handler — if you're not using PSR-15, handlers that is).

You can also supply a PSR-11 compatible container, and if set, Slim 4 will use this to instantiate middleware or route handers that are registered as strings in the same way that Slim 3 works. The difference this time is that you can use any container that you want to. DI is a good thing, so I recommend that you do this for any non-trivial application.

The final three constructor parameters ($callableResolver, $routeCollector, and $routeResolver) are more specialized and allow you control over how Slim will run invoke on your handler and how it does its routing.

To instantiate a Slim\App, we need a PSR-7 implementation, so we'll use Slim-Psr7, so we start with this Composer command:

$ composer require slim/slim slim/psr7

This installs Slim 4 and Slim-Psr7 for us. It will also install all the required PSR interfaces, FastRoute, and a couple of HTTP helper libraries.

We can now create our public/index.php file:

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

$responseFactory = new Slim\Psr7\Factory\ResponseFactory();
$app = new Slim\App($responseFactory);

Add Routing Middleware

We need to route the URL that the user requests to a handler. This is done by Slim's RoutingMiddleware, let's add that next to index.php:

$routingMiddleware = new Slim\Middleware\RoutingMiddleware(

The RoutingMiddleware needs a route resolver. As we didn't pass in one to the App's constructor, Slim will create its default one, which is suitable for most purposes.

Note also that Slim 4 introduces the addMiddleware() method. This is a type-safe method for adding PSR-15 middleware. Slim continues to support callables for middleware using the add() method for backwards compatibility with Slim 3.

Add Error Middleware

Slim's error handling is robust, is flexible, and handles most situations well, so let's add that too. It should be added as the last piece of middleware, as Slim uses a LIFO middleware stack. We have no other middleware at the moment, so we add it to index.php now:

$errorMiddleware = new Slim\Middleware\ErrorMiddleware(

Add a Route Handler

To respond to a request, we register a route handler against an HTTP method and URI. We can respond to a GET request to / using $app->map() like this: $app->map(['GET'], '/', $handler);  . However it is more common to use the helper methods on App for each HTTP method: $app->get('/', $handler) .   $handler can be a callable, a string to be resolved by the DI container, or a PSR-15 instance.

We'll use a closure in index.php:

$app->get('/', function (
    Psr\Http\Message\ServerRequestInterface $request,
    Psr\Http\Message\ResponseInterface $response,
    array $args
): Psr\Http\Message\ResponseInterface {
    $response->getBody()->write("hello world");
    return $response;

As you can see, a callable route handler is given a request object, a response object and an array of route arguments. It must return a response object. The $responseobject that you are passed is specifically created for this handler by Slim using the PSR-17 ResponseFactory it was given in the constructor. This means that your route handler can be completely PSR-7-independent if you wish.

It's far more common in larger applications to use a class for the route handler though, as it's easier to deal with dependencies.

Run the Application

Finally, we can run our application. We call the run() method, passing in a PSR-7 ServerRequest object. This is the final part of index.php:

$request = Slim\Psr7\Factory\ServerRequestFactory::createFromGlobals();

We can start the built-in PHP server and test:

$ php -S -t public/

$ curl -i http://localhost:8888
HTTP/1.1 200 OK
Host: localhost:8888
Content-type: text/html; charset=UTF-8

hello world

It all works, and the response contains the correct status code and content-type header, as you would expect.

The Recommended Way

That's a lot of code to get hello world working. While giving you all the flexibility to choose your own components, Slim remains true to its roots and provides a helper AppFactory class and useful functions on App to make it much easier.

This is what the entire public/index.php looks like when using the helpers:


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

$app = Slim\Factory\AppFactory::create();

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

$app->get('/', function (
    Psr\Http\Message\ServerRequestInterface $request,
    Psr\Http\Message\ResponseInterface $response,
    array $args
): Psr\Http\Message\ResponseInterface {
    $response->getBody()->write("hello world");
    return $response;


There is much less boiler plate code with the recommended approach, as the AppFactory and the addXyzMiddleware() methods do all the required setup for us. Also, the run() method will create a valid request object if we don't supply one.

PSR-7 Independence

What's really nice about using AppFactory::create() is that it will work out which PSR-7 implementation you have installed and use it. This means that you could, for instance, use Diactoros instead:

$ composer require slim/slim zendframework/zend-diactoros

Our public/index.php works without any changes.

In Summary

Slim continues to be a great choice for a microframework that lets you build applications your way by allowing you to choose the most suitable components from Packagist as you see fit.

If you want to look at some example applications these are worth a look:

If you have questions or comments, Slack or the forums are good places to go.

framework, hello world, php, slim 4, tutorial, web dev

Published at DZone with permission of Rob Allen , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}