Posts Tagged ‘slim’

Upgrading LAC to Slim 4

Wednesday, October 28th, 2020 | Programming

Last month, I published an upgrade guide to Slim 4 covering the changes that most people will need to make.

I recently upgraded the Leeds Anxiety Clinic and this project has some further complexities, so this post will elaborate on all of the changes I made, in case my original blog post did not cover some of the issues that you are also running into.

Things to do in advance

The old service layer calls no longer work:

$db = $this->ci->db;

And need to be updated to:

$db = $this->ci->get('db');

However, Slim 3’s service container already supports this syntax, so you can go ahead and update your code in advance.

If you are passing the container into controller functions, you need to typecast it.

use Psr\Container\ContainerInterface;

class Controller {
    __construct(ContainerInterface $ci) {}
}

If you pull the request out from the service container, you cannot do that in Slim 4. For example, if you have a render helper that relies on the request being in the container, you will have to start manually passing that into your render help from the page route closure.

Dependencies

You will want all of these:

"slim/slim": "4.*",
"slim/psr7": "1.*",
"slim/http": "1.*",
"php-di/php-di": "^6.1",

I did wonder if I could remove my other PSR-7 library that I use for Mailgun, nyholm/psr7, but the answer is no.

Instanciating the app

We now create the container and then the app, and you can recursively pass in the container.

$container = new \DI\Container;

$container->set('serviceA', function() use ($container) {
    return new ServiceA($container->get('serviceB'));
});

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

Throwing not found exceptions

If you manually throw not found exceptions or other HTTP exceptions, Slim 3 has them located here:

Slim\Exception\NotFoundException

Slim 4 moves it to here:

Slim\Exception\HttpNotFoundException

Error handling

If you want Slim 4’s default error handling, you need:

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

And if you want to handle HTTP errors (such as not found), you can use:

$errorMiddleware->setErrorHandler(
    Slim\Exception\HttpNotFoundException::class,
    function (Psr\Http\Message\ServerRequestInterface $request) use ($container) {
        $controller = new App\Controller\ExceptionController($container);
        return $controller->notFound($request);
    });

You can also set your own error handling:

$errorMiddleware->setDefaultErrorHandler(
        function (Psr\Http\Message\ServerRequestInterface $request,
        Throwable $exception) use ($container) {
            $controller = new App\Controller\ExceptionController($container);
            return $controller->error($request, $exception);
        });

This means you will need to create your own response object in any exception controller you use.

public function notFound(Request $request)
{
    $response = new \Slim\Psr7\Response;
    return $this->render($response, 'not-found.html');
}

Custom middleware

The way we pass through middleware has changed. The old way:

public function __invoke($request, $response, $next)
{
    $response = $next($request, $response);
    return $response;
}

The new way:

public function __invoke($request, $handler)
{
    return $handler->handle($request);
}

That change alone probably won’t do what you want it to do out-of-the-box, so you might need to do some reading up and adapt it to your specific middleware depending on function.

Custom middleware wants to go towards the bottom after you define your routes, but before the error middleware.

Upgrading from Slim 3 to Slim 4

Friday, September 18th, 2020 | Programming

Slim is one of my favourite PHP microframeworks and many websites are built on Slim 3. I have recently moved to Slim 4 and thought I would document the upgrade process for anyone else looking to make the leap.

Dependencies

Slim 3 came with its own dependency injection container. This is no longer the case. Therefore, we need to bring one in, such as php-di that Slim supports out-of-the-box. We will also need a PSR-7 library and the Slim HTTP helpers.

"slim/slim": "4.*",
"slim/psr7": "1.*",
"slim/http": "1.*",
"php-di/php-di": "^6.1",

Creating the app

In Slim 3, we created the app and then accessed the container.

$app = new \Slim\App([
    'settings' => []
]);

$container = $app->getContainer();

In Slim 4, we create the container then attached it to the app.

$container = new \DI\Container();
\Slim\Factory\AppFactory::setContainer($container);
$app = \Slim\Factory\AppFactory::create();

You can still access the container in the old way and inject dependencies into it, but you need to manually pass it into the app as above.

Accessing dependencies

Now we are using our PSR-11 DI of choice, we need to change how we access our dependencies. Previously, wee could use the Slim shorthand.

$db = $this->ci->db;

Now we need to use the PSR-11 standard.

$db = $this->ci->get('db');

Exception handling

Previously, we could set error handling using the dependency injection container.

$container['notFoundHandler'] = function ($container) {
    return function ($request, $response) use ($container) {
        $controller = new \App\Controller\ExceptionController($container);
        return $controller->notFound($request, $response);
    };
};

In Slim 4, we need to use the bundled middleware.

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

$errorMiddleware->setErrorHandler(
    Slim\Exception\HttpNotFoundException::class,
    function (Psr\Http\Message\ServerRequestInterface $request) use ($container) {
        $controller = new App\Controller\ExceptionController($container);
        return $controller->notFound($request);
    });

This also means changing the exception controller, too, if you use one. In Slim 3, we would still get a response object passed in.

    public function notFound(Request $request, Response $response)
    {
        return $this->render($response, 'not-found.html');
    }

With Slim 4, we need to create our own.

    public function notFound(Request $request)
    {
        $response = new \Slim\Psr7\Response;
        return $this->render($response, 'not-found.html');
    }

That should take care of most of the changes. If you run into anything else, let me know, and I’ll update this article.

Slim PHP 3.12.3

Friday, December 6th, 2019 | Programming

If you’re using the Slim framework in PHP, there is a breaking change between 3.12.2 and 3.12.3. You’ll need to change where you are inheriting your class from.

- use Interop\Container\ContainerInterface;
+ use Psr\Container\ContainerInterface;

Slim

Tuesday, July 3rd, 2012 | Limited, Programming

Slim is a PHP micro framework, similar to Flight, Silex and Limonade, not to be confused by the Ruby templating system of the same name. It claims to contain “everything you need and nothing you don’t.”

If functions like you would expect a micro framework to work. Here is the standard example.

<?php
require 'Slim/Slim.php';
$app = new Slim();
$app->get('/hello/:name', function ($name) {
    echo "Hello, $name!";
});
$app->run();
?>

My favourite part of Slim, however, is actually the Slim Extras bundle which doesn’t ship with it, but can easily be downloaded and dropped in. This adds easy integration for lots of different templating languages – notably Smarty, Twig and Mustache.

So, for example, if you wanted to integrate Twig, just grab the Extras bundle, the Twig bundle, include the relevant file and change your initialisation statement to the following.

$app = new Slim(array("view" => "TwigView"));

That’s all – now you’re away and can call the render method with a filename and data array to render a template using Twig.