Google News
logo
Slim Framework Interview Questions
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs. Like other PHP frameworks, slim also supports routers, middlewares, bodyparser, page templates, encrypted cookies and much more.
First, you need a web server like Nginx or Apache. You should configure your web server so that it sends all appropriate requests to one “front-controller” PHP file. You instantiate and run your Slim app in this PHP file.
 
A Slim app contains routes that respond to specific HTTP requests. Each route invokes a callback and returns an HTTP response. To get started, you first instantiate and configure the Slim application. Next, you define your application routes. Finally, you run the Slim application. It’s that easy. Here’s an example application :
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

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

/**
 * Instantiate App
 *
 * In order for the factory to work you need to ensure you have installed
 * a supported PSR-7 implementation of your choice e.g.: Slim PSR-7 and a supported
 * ServerRequest creator (included with Slim PSR-7)
 */
$app = AppFactory::create();

/**
  * The routing middleware should be added earlier than the ErrorMiddleware
  * Otherwise exceptions thrown from it will not be handled by the middleware
  */
$app->addRoutingMiddleware();

/**
 * Add Error Middleware
 *
 * @param bool                  $displayErrorDetails -> Should be set to false in production
 * @param bool                  $logErrors -> Parameter is passed to the default ErrorHandler
 * @param bool                  $logErrorDetails -> Display error details in error log
 * @param LoggerInterface|null  $logger -> Optional PSR-3 Logger  
 *
 * Note: This middleware should be added last. It will not handle any exceptions/errors
 * for middleware added after it.
 */
$errorMiddleware = $app->addErrorMiddleware(true, true, true);

// Define app routes
$app->get('/hello/{name}', function (Request $request, Response $response, $args) {
    $name = $args['name'];
    $response->getBody()->write("Hello, $name");
    return $response;
});

// Run app
$app->run();
Slim Version : V2
 
* PHP >= 5.3.0
* The mcrypt extension is required only if you use encrypted cookies.
 
Slim Version : V3
 
* Web server with URL rewriting
* PHP 5.5 or newer
 
Slim Version : V4
 
* Web server with URL rewriting
* PHP 7.4 or newer
Step 1: Install Composer
* Don’t have Composer? It’s easy to install by following the instructions on their download page.
 
Step 2: Install Slim
We recommend you install Slim with Composer. Navigate into your project’s root directory and execute the bash command shown below. This command downloads the Slim Framework and its third-party dependencies into your project’s vendor/ directory.
composer require slim/slim:"4.*"
Step 3: Install a PSR-7 Implementation and ServerRequest Creator : 
Before you can get up and running with Slim you will need to choose a PSR-7 implementation that best fits your application. In order for auto-detection to work and enable you to use AppFactory::create() and App::run() without having to manually create a ServerRequest you need to install one of the following implementations:
 
Slim PSR-7
composer require slim/psr7
Nyholm PSR-7 and Nyholm PSR-7 Server
composer require nyholm/psr7 nyholm/psr7-server
Guzzle PSR-7
For usage with Guzzle PSR-7 version 2:
composer require guzzlehttp/psr7 "^2"
For usage with Guzzle PSR-7 version 1:
composer require guzzlehttp/psr7 "^1"
composer require sapphirecat/slim4-http-interop-adapter
Laminas Diactoros
composer require laminas/laminas-diactoros​


Step 4: Hello World
File: public/index.php
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write("Hello world!");
    return $response;
});

$app->run();
It is typical to use the front-controller pattern to funnel appropriate HTTP requests received by your web server to a single PHP file. The instructions below explain how to tell your web server to send HTTP requests to your PHP front-controller file.
Run the following command in terminal to start localhost web server, assuming ./public/ is public-accessible directory with index.php file :
cd public/
php -S localhost:8888
If you are not using index.php as your entry point then change appropriately.
Ensure that the Apache mod_rewrite module is installed and enabled. In order to enable mod_rewrite you can type the following command in the terminal :
sudo a2enmod rewrite
sudo a2enmod actions
Ensure your .htaccess and index.php files are in the same public-accessible directory. The .htaccess file should contain this code:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
To ensure that the public/ directory does not appear in the URL, you should add a second .htaccess file above the public/ directory with the following internal redirect rule:
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]

 

These .htaccess files require URL rewriting.

Make sure to enable Apache’s mod_rewrite module and your virtual host is configured with the AllowOverride option so that the .htaccess rewrite rules can be used: To do this, the file /etc/apache2/apache2.conf must be opened in an editor with root privileges.
 
Change the <Directory ...> directive from AllowOveride None to AllowOveride All.
 
Example : 
<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
Finally, the configuration of Apache must be reloaded. To restart Apache web server, enter :
sudo service apache2 restart
This command works on most Debian/Ubuntu variants. For all other Linux distributions, please consult the documentation of your specific Linux distribution to find out how to restart Apache.
This example assumes that the front controller is located in public/index.php.
 
To “redirect” the sub-directory to the front-controller create a second .htaccess file above the public/ directory.
 
The second .htaccess file should contain this code:
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
You may also set the base path so that the router can match the URL from the browser with the path set in the route registration. This is done with the setBasePath() method.
$app->setBasePath('/myapp');
If you control your server, then you should set up a deployment process using any one of the many deployment system such as:
 
* Deploybot
* Capistrano
* Script controlled with Phing, Make, Ant, etc.

Review the Web Servers documentation to configure your webserver.
 
Deploying to a shared server : If your shared server runs Apache, then you need to create a .htaccess file in your web server root directory (usually named htdocs, public, public_html or www) with the following content:
<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteRule ^$ public/ [L]
   RewriteRule (^[^/]*$) public/$1 [L]
</IfModule>
(replace ‘public’ with the correct name of your domain name e.g. example.com/$1)
 
Now upload all the files that make up your Slim project to the webserver. As you are on shared hosting, this is probably done via FTP and you can use any FTP client, such as Filezilla to do this.
1. Instantiation :  First, you instantiate the Slim\App class. This is the Slim application object. During instantiation, Slim registers default services for each application dependency.
 
2. Route Definitions : Second, you define routes using the application instance’s get(), post(), put(), delete(), patch(), head(), and options() routing methods. These instance methods register a route with the application’s Router object. Each routing method returns the Route instance so you can immediately invoke the Route instance’s methods to add middleware or assign a name.
 
3. Application Runner : Third, you invoke the application instance’s run() method. This method starts the following process:
 
A. Enter Middleware Stack : The run() method begins to inwardly traverse the application’s middleware stack. This is a concentric structure of middleware layers that receive (and optionally manipulate) the Environment, Request, and Response objects before (and after) the Slim application runs. The Slim application is the inner-most layer of the concentric middleware structure. Each middleware layer is invoked inwardly beginning from the outer-most layer.
 
B. Run Application : After the run() method reaches the inner-most middleware layer, it invokes the application instance and dispatches the current HTTP request to the appropriate application route object. If a route matches the HTTP method and URI, the route’s middleware and callable are invoked. If a matching route is not found, the Not Found or Not Allowed handler is invoked.
 
C. Exit Middleware Stack : After the application dispatch process completes, each middleware layer reclaims control outwardly, beginning from the inner-most layer.
 
D. Send HTTP Response : After the outer-most middleware layer cedes control, the application instance prepares, serializes, and returns the HTTP response. The HTTP response headers are set with PHP’s native header() method, and the HTTP response body is output to the current output buffer.
PSR-7 : Slim supports PSR-7 interfaces for its Request and Response objects. This makes Slim flexible because it can use any PSR-7 implementation. For example, you could return an instance of GuzzleHttp\Psr7\CachingStream or any instance returned by the GuzzleHttp\Psr7\stream_for() function.

Value objects : Request and Response objects are immutable value objects. They can be “changed” only by requesting a cloned version that has updated property values. Value objects have a nominal overhead because they must be cloned when their properties are updated. This overhead does not affect performance in any meaningful way.
 
You can request a copy of a value object by invoking any of its PSR-7 interface methods (these methods typically have a with prefix). For example, a PSR-7 Response object has a withHeader($name, $value) method that returns a cloned value object with the new HTTP header.
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

$app->get('/foo', function (Request $request, Response $response, array $args) {
    $payload = json_encode(['hello' => 'world'], JSON_PRETTY_PRINT);
    $response->getBody()->write($payload);
    return $response->withHeader('Content-Type', 'application/json');
});

$app->run();
The PSR-7 interface provides these methods to transform Request and Response objects:
 
* withProtocolVersion($version)
* withHeader($name, $value)
* withAddedHeader($name, $value)
* withoutHeader($name)
* withBody(StreamInterface $body)

The PSR-7 interface provides these methods to transform Request objects :
 
* withMethod($method)
* withUri(UriInterface $uri, $preserveHost = false)
* withCookieParams(array $cookies)
* withQueryParams(array $query)
* withUploadedFiles(array $uploadedFiles)
* withParsedBody($data)
* withAttribute($name, $value)
* withoutAttribute($name)

The PSR-7 interface provides these methods to transform Response objects:
 
* withStatus($code, $reasonPhrase = '')
A middleware implements the PSR-15 Middleware Interface:
 
1. Psr\Http\Message\ServerRequestInterface - The PSR-7 request object
2. Psr\Http\Server\RequestHandlerInterface - The PSR-15 request handler object

It can do whatever is appropriate with these objects. The only hard requirement is that a middleware MUST return an instance of Psr\Http\Message\ResponseInterface. Each middleware SHOULD invoke the next middleware and pass it the Request object as argument.
Different frameworks use middleware differently. Slim adds middleware as concentric layers surrounding your core application. Each new middleware layer surrounds any existing middleware layers. The concentric structure expands outwardly as additional middleware layers are added.
 
The last middleware layer added is the first to be executed.
 
When you run the Slim application, the Request object traverses the middleware structure from the outside in. They first enter the outer-most middleware, then the next outer-most middleware, (and so on), until they ultimately arrive at the Slim application itself. After the Slim application dispatches the appropriate route, the resultant Response object exits the Slim application and traverses the middleware structure from the inside out. Ultimately, a final Response object exits the outer-most middleware, is serialized into a raw HTTP response, and is returned to the HTTP client. Here’s a diagram that illustrates the middleware process flow :

Middleware
Middleware is a callable that accepts two arguments: a Request object and a RequestHandler object. Each middleware MUST return an instance of Psr\Http\Message\ResponseInterface.
 
Closure middleware example : This example middleware is a Closure.
<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
use Slim\Psr7\Response;

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

$app = AppFactory::create();

/**
 * Example middleware closure
 *
 * @param  ServerRequest  $request PSR-7 request
 * @param  RequestHandler $handler PSR-15 request handler
 *
 * @return Response
 */
$beforeMiddleware = function (Request $request, RequestHandler $handler) {
    $response = $handler->handle($request);
    $existingContent = (string) $response->getBody();

    $response = new Response();
    $response->getBody()->write('BEFORE' . $existingContent);

    return $response;
};

$afterMiddleware = function ($request, $handler) {
    $response = $handler->handle($request);
    $response->getBody()->write('AFTER');
    return $response;
};

$app->add($beforeMiddleware);
$app->add($afterMiddleware);

// ...

$app->run();
Slim uses an optional dependency container to prepare, manage, and inject application dependencies. Slim supports containers that implement PSR-11 like PHP-DI.
 
Example usage with PHP-DI : You don’t have to provide a dependency container. If you do, however, you must provide an instance of the container to AppFactory before creating an App.
<?php
use DI\Container;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

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

// Create Container using PHP-DI
$container = new Container();

// Set container to create App with on AppFactory
AppFactory::setContainer($container);
$app = AppFactory::create();
Add a service to your container :
$container->set('myService', function () {
    $settings = [...];
    return new MyService($settings);
});
You can fetch services from your container explicitly as well as from inside a Slim application route like this:
/**
 * Example GET route
 *
 * @param  ServerRequestInterface $request  PSR-7 request
 * @param  ResponseInterface      $response  PSR-7 response
 * @param  array                  $args Route parameters
 *
 * @return ResponseInterface
 */
$app->get('/foo', function (Request $request, Response $response, $args) {
    $myService = $this->get('myService');

    // ...do something with $myService...

    return $response;
});
To test if a service exists in the container before using it, use the has() method, like this:
/**
 * Example GET route
 *
 * @param  ServerRequestInterface $request  PSR-7 request
 * @param  ResponseInterface      $response  PSR-7 response
 * @param  array                  $args Route parameters
 *
 * @return ResponseInterface
 */
$app->get('/foo', function (Request $request, Response $response, $args) {
    if ($this->has('myService')) {
        $myService = $this->get('myService');
    }
    return $response;
});
In case you want to create the App with dependencies already defined in your container, you can use the AppFactory::createFromContainer() method.
 
Example : 
<?php

use App\Factory\MyResponseFactory;
use DI\Container;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Slim\Factory\AppFactory;

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

// Create Container using PHP-DI
$container = new Container();

// Add custom response factory
$container->set(ResponseFactoryInterface::class, function (ContainerInterface $container) {
    return new MyResponseFactory(...);
});

// Configure the application via container
$app = AppFactory::createFromContainer($container);

// ...

$app->run();
Supported App dependencies are :

* Psr\Http\Message\ResponseFactoryInterface
* Slim\Interfaces\CallableResolverInterface
* Slim\Interfaces\RouteCollectorInterface
* Slim\Interfaces\RouteResolverInterface
* Slim\Interfaces\MiddlewareDispatcherInterface
The Application Slim\App is the entry point to your Slim application and is used to register the routes that link to your callbacks or controllers.
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

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

// Instantiate app
$app = AppFactory::create();

// Add Error Handling Middleware
$app->addErrorMiddleware(true, false, false);

// Add route callbacks
$app->get('/', function (Request $request, Response $response, array $args) {
    $response->getBody()->write('Hello World');
    return $response;
});

// Run application
$app->run();
Your Slim app’s routes and middleware are given a PSR-7 request object that represents the current HTTP request received by your web server. The request object implements the PSR-7 ServerRequestInterface with which you can inspect and manipulate the HTTP request method, headers, and body.
 
How to get the Request object : The PSR-7 request object is injected into your Slim application routes as the first argument to the route callback like this:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

$app->get('/hello', function (Request $request, Response $response) {
    $response->getBody()->write('Hello World');
    return $response;
});

$app->run();
 
The PSR-7 request object is injected into your Slim application middleware as the first argument of the middleware callable like this :
<?php

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

$app->add(function (Request $request, RequestHandler $handler) {
   return $handler->handle($request);
});

// ...define app routes...

$app->run();
Every HTTP request has a method that is typically one of:
 
* GET
* POST
* PUT
* DELETE
* HEAD
* PATCH
* OPTIONS

You can inspect the HTTP request’s method with the Request object method appropriately named getMethod().
$method = $request->getMethod();
It is possible to fake or override the HTTP request method. This is useful if, for example, you need to mimic a PUT request using a traditional web browser that only supports GET or POST requests.
 
There are two ways to override the HTTP request method. You can include a METHOD parameter in a POST request’s body. The HTTP request must use the application/x-www-form-urlencoded content type.
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 22

data=value&_METHOD=PUT
 
You can also override the HTTP request method with a custom X-Http-Method-Override HTTP request header. This works with any HTTP request content type.
POST /path HTTP/1.1
Host: example.com
Content-type: application/json
Content-length: 16
X-Http-Method-Override: PUT

{"data":"value"}
Every HTTP request has a URI that identifies the requested application resource. The HTTP request URI has several parts :
 
* Scheme (e.g. http or https)
* Host (e.g. example.com)
* Port (e.g. 80 or 443)
* Path (e.g. /users/1)
* Query string (e.g. sort=created&dir=asc)

You can fetch the PSR-7 Request object’s URI object with its getUri() method:
$uri = $request->getUri();
The PSR-7 Request object’s URI is itself an object that provides the following methods to inspect the HTTP request’s URL parts:
 
* getScheme()
* getAuthority()
* getUserInfo()
* getHost()
* getPort()
* getPath()
* getQuery() (returns the full query string, e.g. a=1&b=2)
* getFragment()

You can get the query parameters as an associative array on the Request object using getQueryParams().
Sometimes in middleware you require the parameter of your route.
 
In this example we are checking first that the user is logged in and second that the user has permissions to view the particular video they are attempting to view.
$app
  ->get('/course/{id}', Video::class . ':watch')
  ->add(PermissionMiddleware::class);
<?php

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Routing\RouteContext;

class PermissionMiddleware
{
    public function __invoke(Request $request, RequestHandler $handler)
    {
        $routeContext = RouteContext::fromRequest($request);
        $route = $routeContext->getRoute();
        
        $courseId = $route->getArgument('id');
        
        // do permission logic...
        
        return $handler->handle($request);
    }
}
The Slim Framework’s router is built on top of the Fast Route component, and it is remarkably fast and stable. While we are using this component to do all our routing, the app’s core has been entirely decoupled from it and interfaces have been put in place to pave the way for using other routing libraries.
You can define application routes using proxy methods on the Slim\App instance. The Slim Framework provides methods for the most popular HTTP methods.
 
GET Route : You can add a route that handles only GET HTTP requests with the Slim application’s get() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->get('/books/{id}', function ($request, $response, array $args) {
    // Show book identified by $args['id']
});
POST Route : You can add a route that handles only POST HTTP requests with the Slim application’s post() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->post('/books', function ($request, $response, array $args) {
    // Create new book
});
PUT Route : You can add a route that handles only PUT HTTP requests with the Slim application’s put() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->put('/books/{id}', function ($request, $response, array $args) {
    // Update book identified by $args['id']
});
DELETE Route : You can add a route that handles only DELETE HTTP requests with the Slim application’s delete() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->delete('/books/{id}', function ($request, $response, array $args) {
    // Delete book identified by $args['id']
});
OPTIONS Route : You can add a route that handles only OPTIONS HTTP requests with the Slim application’s options() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->options('/books/{id}', function ($request, $response, array $args) {
    // Return response headers
});
PATCH Route : You can add a route that handles only PATCH HTTP requests with the Slim application’s patch() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->patch('/books/{id}', function ($request, $response, array $args) {
    // Apply changes to book identified by $args['id']
});
Any Route : You can add a route that handles all HTTP request methods with the Slim application’s any() method. It accepts two arguments:
 
* The route pattern (with optional named placeholders)
* The route callback
$app->any('/books/[{id}]', function ($request, $response, array $args) {
    // Apply changes to books or book identified by $args['id'] if specified.
    // To check which method is used: $request->getMethod();
});
Note that the second parameter is a callback. You could specify a Class which implementes the __invoke() method instead of a Closure. You can then do the mapping somewhere else:
$app->any('/user', 'MyRestfulController');
Custom Route : You can add a route that handles multiple HTTP request methods with the Slim application’s map() method. It accepts three arguments:
 
* Array of HTTP methods
* The route pattern (with optional named placeholders)
* The route callback
$app->map(['GET', 'POST'], '/books', function ($request, $response, array $args) {
    // Create new book or list all books
});​
Each routing method described above accepts a callback routine as its final argument. This argument can be any PHP callable, and by default it accepts three arguments.
 
* Request The first argument is a Psr\Http\Message\ServerRequestInterface object that represents the current HTTP request.
* Response The second argument is a Psr\Http\Message\ResponseInterface object that represents the current HTTP response.
* Arguments The third argument is an associative array that contains values for the current route’s named placeholders.
If you use a dependency container and a Closure instance as the route callback, the closure’s state is bound to the Container instance. This means you will have access to the DI container instance inside of the Closure via the $this keyword:
$app->get('/hello/{name}', function ($request, $response, array $args) {
    // Use app HTTP cookie service
    $this->get('cookies')->set('name', [
        'value' => $args['name'],
        'expires' => '7 days'
    ]);
})
To help organize routes into logical groups, the Slim\App also provides a group() method. Each group’s route pattern is prepended to the routes or groups contained within it, and any placeholder arguments in the group pattern are ultimately made available to the nested routes:
use Slim\Routing\RouteCollectorProxy;
// ...

$app->group('/users/{id:[0-9]+}', function (RouteCollectorProxy $group) {
    $group->map(['GET', 'DELETE', 'PATCH', 'PUT'], '', function ($request, $response, array $args) {
        // Find, delete, patch or replace user identified by $args['id']
        // ...
        
        return $response;
    })->setName('user');
    
    $group->get('/reset-password', function ($request, $response, array $args) {
        // Route for /users/{id:[0-9]+}/reset-password
        // Reset the password for user identified by $args['id']
        // ...
        
        return $response;
    })->setName('user-password-reset');
});
You are not limited to defining a function for your routes. In Slim there are a few different ways to define your route action functions.
 
In addition to a function, you may use:
 
* container_key:method
* Class:method
* Class implementing __invoke() method
* container_key

This functionality is enabled by Slim’s Callable Resolver Class. It translates a string entry into a function call. Example:
$app->get('/', '\HomeController:home');
Alternatively, you can take advantage of PHP’s ::class operator which works well with IDE lookup systems and produces the same result:
$app->get('/', \HomeController::class . ':home');
You can also pass an array, the first element of which will contain the name of the class, and the second will contain the name of the method being called:
$app->get('/', [\HomeController::class, 'home']);
In this code above we are defining a / route and telling Slim to execute the home() method on the HomeController class.
 
Slim first looks for an entry of HomeController in the container, if it’s found it will use that instance otherwise it will call it’s constructor with the container as the first argument. Once an instance of the class is created it will then call the specified method using whatever Strategy you have defined.
The routing has been implemented as middleware. We are still using FastRoute as the default router but it is not tightly coupled to it. If you wanted to implement another routing library you could by creating your own implementations of the routing interfaces. DispatcherInterface, RouteCollectorInterface, RouteParserInterface and RouteResolverInterface which create a bridge between Slim’s components and the routing library. If you were using determineRouteBeforeAppMiddleware, you need to add the Middleware\RoutingMiddleware middleware to your application just before your call run() to maintain the previous behaviour.
<?php
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

// Add Routing Middleware
$app->addRoutingMiddleware();

// ...

$app->run();
Things go wrong. You can’t predict errors, but you can anticipate them. Each Slim Framework application has an error handler that receives all uncaught PHP exceptions. This error handler also receives the current HTTP request and response objects, too. The error handler must prepare and return an appropriate Response object to be returned to the HTTP client.
<?php
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

/**
 * The routing middleware should be added earlier than the ErrorMiddleware
 * Otherwise exceptions thrown from it will not be handled by the middleware
 */
$app->addRoutingMiddleware();

/**
 * Add Error Middleware
 *
 * @param bool                  $displayErrorDetails -> Should be set to false in production
 * @param bool                  $logErrors -> Parameter is passed to the default ErrorHandler
 * @param bool                  $logErrorDetails -> Display error details in error log
 * @param LoggerInterface|null  $logger -> Optional PSR-3 Logger  
 *
 * Note: This middleware should be added last. It will not handle any exceptions/errors
 * for middleware added after it.
 */
$errorMiddleware = $app->addErrorMiddleware(true, true, true);

// ...

$app->run();
The rendering is finally decoupled from the handling. It will still detect the content-type and render things appropriately with the help of ErrorRenderers. The core ErrorHandler extends the AbstractErrorHandler class which has been completely refactored. By default it will call the appropriate ErrorRenderer for the supported content types. The core ErrorHandler defines renderers for the following content types :
 
* application/json
* application/xml and text/xml
* text/html
* text/plain

For any content type you can register your own error renderer. So first define a new error renderer that implements \Slim\Interfaces\ErrorRendererInterface.
<?php
use Slim\Interfaces\ErrorRendererInterface;
use Throwable;

class MyCustomErrorRenderer implements ErrorRendererInterface
{
    public function __invoke(Throwable $exception, bool $displayErrorDetails): string
    {
        return 'My awesome format';
    }
}
And then register that error renderer in the core error handler. In the example below we will register the renderer to be used for text/html content types.
<?php
use MyApp\Handlers\MyErrorHandler;
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

// Add Routing Middleware
$app->addRoutingMiddleware();

// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(true, true, true);

// Get the default error handler and register my custom error renderer.
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', MyCustomErrorRenderer::class);

// ...

$app->run();
The Method Overidding Middleware enables you to use the X-Http-Method-Override request header or the request body parameter _METHOD to override an incoming request’s method. The middleware should be placed after the routing middleware has been added.
<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\MethodOverrideMiddleware;

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

$app = AppFactory::create();

// Add RoutingMiddleware before we add the MethodOverrideMiddleware so the method is overrode before routing is done
$app->addRoutingMiddleware();

// Add MethodOverride middleware
$methodOverrideMiddleware = new MethodOverrideMiddleware();
$app->add($methodOverrideMiddleware);

// ...

$app->run();
The Output Buffering Middleware enables you to switch between two modes of output buffering: APPEND (default) and PREPEND mode. The APPEND mode will use the existing response body to append the contents. The PREPEND mode will create a new response body object and prepend the contents to the output from the existing response body. This middleware should be placed on the center of the middleware stack so it gets executed last.
<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\OutputBufferingMiddleware;
use Slim\Psr7\Factory\StreamFactory;

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

$app = AppFactory::create();

$streamFactory = new StreamFactory();

/**
 * The two modes available are
 * OutputBufferingMiddleware::APPEND (default mode) - Appends to existing response body
 * OutputBufferingMiddleware::PREPEND - Creates entirely new response body
 */
$mode = OutputBufferingMiddleware::APPEND;
$outputBufferingMiddleware = new OutputBufferingMiddleware($streamFactory, $mode);
$app->add($outputBufferingMiddleware);

// ...

$app->run();
It’s very common in web APIs to send data in JSON or XML format. Out of the box, PSR-7 implementations do not support these formats, you have to decode the Request object’s getBody() yourself. As this is a common requirement, Slim 4 provides BodyParsingMiddleware to handle this task.
 
It’s recommended to put the body parsing middleware before the call to addErrorMiddlware, so that the stack looks like this :
<?php

use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

// Parse json, form data and xml
$app->addBodyParsingMiddleware();

$app->addRoutingMiddleware();

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

// ...

$app->run();


Posted JSON, form or XML data :

No changes are required to the POST handler because the BodyParsingMiddleware detects that the Content-Type is set to a JSON media type and so places the decoded body into the Request’s parsed body property.

 

For data posted to the website from a browser, you can use the $request’s getParsedBody() method.

This will return an array of the posted data.

$app->post('/', function (Request $request, Response $response, $args): Response {

    $data = $request->getParsedBody();

    

    $html = var_export($data, true);

    $response->getBody()->write($html);

    

    return $response;

});
* The middleware reads the Content-Type from the request header to detect the media type.
* Checks if this specific media type has a parser registered
* If not, look for a media type with a structured syntax suffix (RFC 6839), e.g. application/*

Supported media types : 
* application/json
* application/x-www-form-urlencoded
* application/xml
* text/xml
The Content Length Middleware will automatically append a Content-Length header to the response. This is to replace the addContentLengthHeader setting that was removed from Slim 3. This middleware should be placed on the end of the middleware stack so that it gets executed first and exited last.
<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\ContentLengthMiddleware;

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

$app = AppFactory::create();

// Add any middleware which may modify the response body before adding the ContentLengthMiddleware

$contentLengthMiddleware = new ContentLengthMiddleware();
$app->add($contentLengthMiddleware);

// ...

$app->run();