升级指南

如果您要从版本 3 升级到版本 4,这些是您需要注意的重大变化。

PHP 版本要求

Slim 4 需要PHP 7.4 或更新版本

对 Slim\App 构造函数的重大更改

Slim 的 App settings 曾经是容器的一部分,现在已经和它解耦了。

/**
 * Slim 3 App::__construct($container = [])
 * As seen here the settings used to be nested
 */
$app = new App([
    'settings' => [...],
]);

/**
 * Slim 4 App::__constructor() method takes 1 mandatory parameter and 4 optional parameters
 *
 * @param ResponseFactoryInterface Any implementation of a ResponseFactory
 * @param ContainerInterface|null Any implementation of a Container
 * @param CallableResolverInterface|null Any implementation of a CallableResolver
 * @param RouteCollectorInterface|null Any implementation of a RouteCollector
 * @param RouteResolverInterface|null Any implementation of a RouteResolver
 */
$app = new App(...);

删除的应用程序设置

容器的变化

Slim 不再有容器,因此您需要提供自己的容器。如果您依赖容器中的请求或响应,那么您需要自己将它们设置到容器中,或者进行重构。此外,App::__call()方法已被删除,因此通过$app->key_name()不再有效访问容器属性。

/**
 * Slim 3.x shipped with the Pimple container implementation and enabled the following syntax
 */
$container = $app->getContainer();

//Assign dependencies as array
$container['view'] = function (\Psr\Container\ContainerInterface $container){
    return new \Slim\Views\Twig('');
};


/**
 * Slim 4.x does not ship with a container library. It supports all PSR-11 implementations such as PHP-DI
 * To install PHP-DI `composer require php-di/php-di`
 */

use Slim\Factory\AppFactory;

$container = new \DI\Container();

AppFactory::setContainer($container);
$app = AppFactory::create();

$container = $app->getContainer();
$container->set('view', function(\Psr\Container\ContainerInterface $container){
    return new \Slim\Views\Twig('');
});

基本路径处理的变化

在 v3 之前,Slim 从实例化应用程序的文件夹中提取基本路径。现在不再是这种情况,并且必须显式声明基本路径,以防您的应用程序不是从域的根目录执行的

use Slim\Factory\AppFactory;
// ...
$app = AppFactory::create();
$app->setBasePath('/my-app-subpath');
// ...
$app->run();

路由组件的变化

Slim 3 中的组件Router已拆分为多个不同的组件,以便将 FastRoute 与核心分离App,并为最终用户提供更大的灵活性。它已被拆分为 RouteCollector,RouteParserRouteResolver这 3 个组件都可以有各自的接口,您可以自己实现这些接口并将其注入到App构造函数中。以下拉取请求提供了很多关于这些新组件的公共接口的见解:

这也意味着Route Groups改变了他们的签名:

$app->group('/user', function(\Slim\Routing\RouteCollectorProxy $app){
    $app->get('', function() { /* ... */ });
    //...
});

新的中间件方法

在 Slim 4 中,我们希望通过解耦 Slim 的一些 App 核心功能并将其作为中间件实现,从而为开发人员提供更大的灵活性。这使您能够交换核心组件的自定义实现。

中间件执行

中间件执行没有改变,仍然Last In First Out (LIFO)和 Slim 3 一样。

新建应用工厂

引入该AppFactory组件是为了减少因将 PSR-7 实现与核心解耦而引起的一些摩擦App它检测在您的项目根目录中安装了哪个 PSR-7 实现和 ServerRequest 创建者,并使您能够通过实例化应用程序AppFactory::create()并使用App::run()而无需传入ServerRequest对象。支持以下 PSR-7 实现和 ServerRequest 创建者组合:

新的路由中间件

路由已作为中间件实现。我们仍在使用FastRoute来满足我们的路由需求。如果您使用的是determineRouteBeforeAppMiddleware,则需要Middleware\RoutingMiddleware在调用之前将中间件添加到您的应用程序run()以保持先前的行为。有关更多信息,请参阅拉取请求 #2288 。

<?php
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

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

// ...

$app->run();

新的错误处理中间件

错误处理也被实现为中间件。有关更多信息,请参阅拉取请求 #2398 。

<?php
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

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

/**
 * Add Error Handling 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
 * which can be replaced by a callable of your choice.

 * Note: This middleware should be added last. It will not handle any exceptions/errors
 * for middleware added after it.
 */
$app->addErrorMiddleware(true, true, true);

// ...

$app->run();

新的 Not Found- and Not Allowed 处理程序

v3 中的404 Not Found 处理程序405 Not Allowed 处理程序可以按如下方式迁移:

<?php
use Psr\Http\Message\ServerRequestInterface;
use Slim\Factory\AppFactory;
use Slim\Exception\HttpNotFoundException;
use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Psr7\Response;

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

$app = AppFactory::create();

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

// Set the Not Found Handler
$errorMiddleware->setErrorHandler(
    HttpNotFoundException::class,
    function (ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails) {
        $response = new Response();
        $response->getBody()->write('404 NOT FOUND');

        return $response->withStatus(404);
    });

// Set the Not Allowed Handler
$errorMiddleware->setErrorHandler(
    HttpMethodNotAllowedException::class,
    function (ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails) {
        $response = new Response();
        $response->getBody()->write('405 NOT ALLOWED');

        return $response->withStatus(405);
    });

新的调度员和路由结果

我们围绕 FastRoute 调度程序创建了一个包装器,它添加了一个结果包装器并可以访问路由的完整允许方法列表,而不是仅在出现异常时才可以访问这些方法。Request 属性routeInfo现已弃用并替换为routingResults. 有关更多信息,请参阅拉取请求 #2405 。

<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteContext;

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

$app = AppFactory::create();

$app->get('/hello/{name}', function (Request $request, Response $response) {
    $routeContext = RouteContext::fromRequest($request);
    $routingResults = $routeContext->getRoutingResults();
    
    // Get all of the route's parsed arguments e.g. ['name' => 'John']
    $routeArguments = $routingResults->getRouteArguments();
    
    // A route's allowed methods are available at all times now and not only when an error arises like in Slim 3
    $allowedMethods = $routingResults->getAllowedMethods();
    
    return $response;
});

// ...

$app->run();

新方法覆盖中间件

如果您使用自定义标头或正文参数覆盖 HTTP 方法,则需要添加中间件Middleware\MethodOverrideMiddleware才能像以前一样覆盖该方法。有关更多信息,请参阅拉取请求 #2329 。

<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\MethodOverridingMiddleware;

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

$app = AppFactory::create();

$methodOverridingMiddleware = new MethodOverrideMiddleware();
$app->add($methodOverridingMiddleware);

// ...

$app->run();

新的内容长度中间件

内容长度中间件会自动将Content-Length标头附加到响应中。这是为了替换addContentLengthHeader从 Slim 3 中删除的设置。这个中间件应该放在中间件堆栈的中心,以便最后执行。

<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\ContentLengthMiddleware;

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

$app = AppFactory::create();

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

// ...

$app->run();

新的输出缓冲中间件

输出缓冲中间件使您能够在两种输出缓冲模式之间切换:(APPEND默认)和PREPEND模式。APPEND模式将使用现有的响应主体来附加内容,而PREPEND模式将创建一个新的响应主体并将其附加到现有的响应中。这个中间件应该放在中间件堆栈的中心,这样它才能最后执行。

<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\OutputBufferingMiddleware;

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

$app = AppFactory::create();

/**
 * 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($mode);

// ...

$app->run();