- Published on
Upgrade Slim framework from 3 to 4
What I needed to do, to upgrade Kwai API to Slim 4 ...
Kwai
Kwai-api is an API for managing a sportsclub website. Instead of using a CMS like Drupal, I've decided to write this by composing Kwai-api with libraries and frameworks because in the past I struggled with upgrading CMS systems from one major version to another.
One of the frameworks used is Slim. Slim describes itself as : "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.". On August 2019, a new major version of Slim was released: 4.0.0.
Upgrading
Slim 4 has some breaking changes. All of them are listed on the Upgrade guide.
Container
Slim 4 has no built-in Container
class anymore. A separate Container library which implements the PSR-11 - Container interface is needed now. No problem, that's the way I like to work: select a library that meets the requirements and use it. I already use some libraries from the The PHP League, so I selected the Container package. Instead of using the constructor of App
, AppFactory
is used to create the Slim Application instance.
$container = new Container();
$container->defaultToShared();
AppFactory::setContainer($container);
$application = AppFactory::create();
Callbacks are used to create objects that are stored in the container. The current Container instance was always passed to this function. With the PHP League implementation this must be set explicitly by calling addArgument
:
$container->add('template', function ($c) {
$dir = $c->get('settings')['template_dir']
return new TemplateEngine($dir);
})->addArgument($container);
AppFactory
is introduced to decouple the PSR-7 implementation. I installed Slim PSR-7.
Kwai API uses an invokable class to execute actions. Slim passes the Container instance in the constructor. The container interface must be changed from
Interop\Container\ContainerInterface
toPsr\Container\ContainerInterface
.
Changes to Routing components
To avoid a big PHP file with a lot of routing information, the first part of the Kwai api points to a PHP file. In this PHP file a routing group is created. In Slim 3 the Application
instance was passed to the group function and the $this
variable was bound to the Application instance. In Slim 4 this is changed to an instance of RouteCollectorProxy
and $this
is now bound to the Container instance. This is logical, because this is the same behaviour as the routing closure.
So this code :
$app = \Core\Clubman::getApplication();
$app->group('/news', function () {
$this->get('/stories', \REST\News\Actions\BrowseStoryAction::class)
->setName('news.browse')
;
...
});
is changed to:
use Slim\Routing\RouteCollectorProxy;
$app = \Core\Clubman::getApplication();
$app->group('/news', function (RouteCollectorProxy $group) {
$group->get('/stories', \REST\News\Actions\BrowseStoryAction::class)
->setName('news.browse')
;
...
});
I also had to set a basepath after creating the Application instance.
$application->setBasePath($basePath);
This wasn't necessary in Slim 3. Because there are also other directories containing API's, I changed the getApplication method and passes the basepath as argument. '/api'
is the default. For judo specific api's, '/api/sport/judo'
is passed.
Changes to Middleware
Our middleware was still using the original interface:
function (
ServerRequestInterface $request,
ResponseInterface $response,
callable $next
) : ResponseInterface
but the final standard has changed to:
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
interface MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
) : ResponseInterface;
}
So each middleware must now implement MiddlewareInterface
.