升级指南
如果您从版本 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 设置
addContentLengthHeader请参阅 内容长度中间件 获取此设置的新实现方式。determineRouteBeforeAppMiddleware将 路由中间件 放置在中间件栈的正确位置以复制现有行为。outputBuffering请参阅 输出缓冲中间件 获取此设置的新实现方式。displayErrorDetails请参阅 错误处理中间件 获取此设置的新实现方式。
容器的更改
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 核心,并为最终用户提供更多灵活性。它被拆分为
RouteCollector、RouteParser 和 RouteResolver。这三个组件都可以有各自的接口,您可以在自己的项目中实现并注入到 App 构造函数中。以下的 Pull Request 提供了关于这些新组件的公共接口的许多见解:
- Pull Request #2604
- Pull Request #2622
- Pull Request #2639
- Pull Request #2640
- Pull Request #2641
- Pull Request #2642
这也意味着 路由组 已更改其签名:
$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 Handler 和 405 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();