升級指南

如果你從 3 版升級到 4 版,以下是你需要注意的重要變更。

PHP 版本需求

Slim 4 需要 PHP 7.4 或更新版本

Slim\App 建構函式的重大變更

Slim 的 App 設定過去是容器的一部分,而現在已從中解耦。

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

已移除的 App 設定

變更為容器

Slim 已不再有 Container,所以你需要提供自己的 Container。如果你依賴 Container 內的 request 或 response,那麼你需要手動將它們設置到容器中,或是進行重構。另外,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。這三個組件都可以有各自的介面,你可以自行實作並注入 App 建構函式。下列 Pull Request 提供了這些新組件的公用介面的許多見解

這也表示路由群組已變更其簽章

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

新的中間件方法

在 Slim 4 中,我們希望透過讓 Slim 的部分應用程式核心功能脫鉤並實作為中間件,來提供開發人員更大的彈性。這樣一來,你就可以替換核心組件的自訂實作。

中間件執行

中間件執行並未改變,仍然是「後進先出 (LIFO)」原則,就跟 Slim 3 一樣。

新的 App Factory

引入 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();

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

// ...

$app->run();

新錯誤處理中介軟體

錯誤處理也已實作為中介軟體。請參閱 Pull Request #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();

新的未找到和不允許處理常式

v3 的 404 未找到處理常式405 不允許處理常式 可改用下列方式進行移轉

<?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 取代。請參閱 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();
    
    // 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 中介軟體,以能夠像以往一樣覆寫方法。請參閱 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();

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