Skip to content

升级指南

如果您从版本 3 升级到版本 4,以下是您需要了解的重要更改。

PHP 版本要求

Slim 4 需要 PHP 7.4 或更高版本

Slim\App 构造函数的变化

Slim 的 App 设置过去是容器的一部分,现在已与容器解耦。

/**
 * Slim 3 App::__construct($container = [])
 * 如下所示,设置过去是嵌套的
 */
$app = new App([
    'settings' => [...],
]);

/**
 * Slim 4 App::__constructor() 方法接受 1 个必需参数和 4 个可选参数
 * 
 * @param ResponseFactoryInterface 任何实现 ResponseFactory 的类
 * @param ContainerInterface|null 任何实现 Container 的类
 * @param CallableResolverInterface|null 任何实现 CallableResolver 的类
 * @param RouteCollectorInterface|null 任何实现 RouteCollector 的类
 * @param RouteResolverInterface|null 任何实现 RouteResolver 的类
 */
$app = new App(...);

移除的 App 设置

容器的更改

Slim 不再提供容器,您需要自己提供。如果您依赖于容器中的请求或响应对象,那么您需要自行将它们设置为容器,或进行重构。另外,已删除了 App::__call() 方法,所以通过 $app->key_name() 访问容器属性的方式不再起作用。

/**
 * Slim 3.x 使用 Pimple 容器实现,并启用以下语法
 */
$container = $app->getContainer();

// 将依赖项分配为数组
$container['view'] = function (\Psr\Container\ContainerInterface $container){
    return new \Slim\Views\Twig('');
};


/**
 * Slim 4.x 不再附带容器库。它支持所有 PSR-11 的实现,如 PHP-DI
 * 要安装 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('');
});

基础路径处理的更改

在版本3之前,Slim 会从应用程序所在的文件夹中提取基础路径。现在不再是这样,必须显式声明基础路径,以防止应用程序不是从域的根目录执行

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

路由组件的更改

Slim 3 的 Router 组件已拆分为多个不同的组件,以解耦 FastRoute 和 App 核心,并为最终用户提供更多灵活性。它被拆分为 RouteCollectorRouteParserRouteResolver。这三个组件都可以有各自的接口,您可以在自己的项目中实现并注入到 App 构造函数中。以下的 Pull Request 提供了关于这些新组件的公共接口的许多见解:

这也意味着 路由组 已更改其签名:

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

新的中间件方法

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

中间件执行顺序

中间件的执行顺序没有变化,仍然是 Last In First Out (LIFO),与 Slim 3 相同。

新的 App 工厂

引入了 AppFactory 组件,以减少将 PSR-7 实现与 App 核心解耦所带来的一些问题。它会检测安装在项目根目录中的 PSR-7 实现和 ServerRequest 创建器,并使您能够通过 AppFactory::create() 实例化应用程序,并使用 App::run() 而无需传递 ServerRequest 对象。支持以下 PSR-7 实现和 ServerRequest 创建器组合:

新的路由中间件

路由已实现为中间件。我们仍然使用 FastRoute 来处理路由。如果您正在使用 determineRouteBeforeAppMiddleware,则需要在调用 run() 之前向应用程序添加 Middleware\RoutingMiddleware 中间件以保持先前的行为。 有关更多信息,请参阅 Pull Request #2288

<?php
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

// 添加路由中间件
$app->addRoutingMiddleware();

// ...

$app->run();

新的错误处理中间件

错误处理也已经实现为中间件。 有关更多信息,请参阅 Pull Request #2398

<?php
use Slim\Factory\AppFactory;

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

$app = AppFactory::create();

/**
 * 在 ErrorMiddleware 之前添加路由中间件
 * 否则它抛出的异常将无法处理
 */
$app->addRoutingMiddleware();

/**
 * 添加错误处理中间件
 *
 * @param bool $displayErrorDetails -> 应该在生产环境中设置为 false
 * @param bool $logErrors -> 参数传递给默认的 ErrorHandler
 * @param bool $logErrorDetails -> 在错误日志中显示错误详细信息
 * 可以使用自定义的可调用函数替代此参数

 * 注意:此中间件应添加在最后。它不会处理在其之后添加的任何中间件产生的异常/错误。
 */
$app->addErrorMiddleware(true, true, true);

// ...

$app->run();

新的未找到和不允许处理程序

v3 中的 404 Not Found Handler405 Not Allowed Handler 可以迁移到以下形式:

<?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);

// 设置 404 Not Found 处理程序
$errorMiddleware->setErrorHandler(
    HttpNotFoundException::class,
    function (ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails) {
        $response = new Response();
        $response->getBody()->write('404 NOT FOUND');

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

// 设置 405 Not Allowed 处理程序
$errorMiddleware->setErrorHandler(
    HttpMethodNotAllowedException::class,
    function (ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails) {
        $response = new Response();
        $response->getBody()->write('405 NOT ALLOWED');

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

新的 Dispatcher 和 Routing Results

我们为 FastRoute 调度器创建了一个包装器,它添加了结果包装器并提供对路由的完整允许方法列表的访问权限,而不仅仅在异常发生时才能访问。Request 属性 routeInfo 现已弃用,并替换为 routingResults。 有关更多信息,请参阅 Pull Request #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();

    // 获取路由的所有解析参数,例如 ['name' => 'John']
    $routeArguments = $routingResults->getRouteArguments();

    // 现在始终可以获取路由的允许方法,不仅限于异常引发时(在 Slim 3 中的行为)
    $allowedMethods = $routingResults->getAllowedMethods();

    return $response;
});

// ...

$app->run();

新的方法覆盖中间件

如果您使用自定义标头或请求体参数来覆盖HTTP方法,您需要添加 Middleware\MethodOverrideMiddleware 中间件以便能够像以前一样覆盖方法。 有关更多信息,请参阅 Pull Request #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 头信息。这是为了替换 Slim 3 中移除的 addContentLengthHeader 设置。此中间件应该放置在中间件栈的中间位置,以便最后执行。

<?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();

/**
 * 可用的两种模式是
 * OutputBufferingMiddleware::APPEND(默认模式) - 追加到现有的响应正文
 * OutputBufferingMiddleware::PREPEND - 创建全新的响应正文
 */
$mode = OutputBufferingMiddleware::APPEND;
$outputBufferingMiddleware = new OutputBufferingMiddleware($mode);

// ...

$app->run();