升级指南

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

PHP 版本要求

Slim 4 要求PHP 7.4 或更高版本

针对 Slim\App 构造函数的中断性更改

Slim 的应用程序设置曾经是容器的一部分,现在已从中分离出来。

/**
 * 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 核心分离,并为最终用户提供更大的灵活性。它已拆分为 RouteCollectorRouteParserRouteResolver。这 3 个组件都可以具有您自己实现并注入到 App 构造函数中各自的接口。以下请求拉取提供了对这些新组件的公共接口的很多见解

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

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

新的中间件方法

在 Slim 4 中,我们希望通过分离 Slim 的一些 App 核心功能并将其实现为中间件,从而为开发者提供更大的灵活性。这使您可以替换核心组件的自定义实现。

中间件执行

中间件执行未更改,并且与 Slim 3 中仍为 后进先出 (LIFO)

新的 App 工厂

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

新路由中间件

路由已作为中间件实现。我们仍在使用FastRoute满足我们的路由需求。如果您正在使用determineRouteBeforeAppMiddleware,则需要在调用run()之前将Middleware\RoutingMiddleware中间件添加到应用程序中,以维护之前的行为。有关详细信息,请参见请求提取#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();

新不存在和不允许处理器

可以如下迁移版本3中的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 调度程序周围创建了一个包装器,该包装器添加了一个结果包装器,并允许访问路由允许的所有方法的完整列表,而不仅仅是在出现异常时才能访问这些方法。请求属性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标头。这是为了替换从 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();

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