以下の手順を参考に作業。
https://codezine.jp/article/detail/11904
ライブラリのバージョンアップ + 追加インストール
//update
composer require slim/slim
composer require monolog/monolog
//追加
composer require slim/psr7
composer require php-di/php-di
移行作業
index.phpの修正
DIコンテナの変更のため、index.phpとdependencies.phpの設定を変更。
Slim\Factory\AppFactoryとDI\Containerを使うように変更。
use Slim\Factory\AppFactory;
use DI\Container;
以下の流れ
settingのjsonを取得。
containerを作成。
containerにsettingをsetしてdependenciesにcontainerを渡してまたcontanierを返してもらう
そのcontainerを素にAppFactoryでcreateする。
// Instantiate the app
$settings = require __DIR__ . '/../src/settings.php';
// Set up dependencies
$container = new Container();
$container->set('settings', $settings['settings']);
$dependencies = require __DIR__ . '/../src/dependencies.php';
$container = $dependencies($container);
AppFactory::setContainer($container);
$app = AppFactory::create();
dependencies.phpはcontainerを受け取るように修正して、
contaier->setで保存するようにする。
use DI\Container;
return function (Container $container) {
$container->set('renderer', function ($c) {
...省略
App/HTTP/系をSlim\Psr7\系に変更
// use Slim\Http\Request;
// use Slim\Http\Response;
use Slim\Psr7\Request;
use Slim\Psr7\Response;
middlewareを変更
クロージャーで作成していたmiddlewareにうまく引数がわたせなくなったので、classで作成するように修正。
$requireLogin = function ($request, $response, $next) {
//
}
//上記処理を
$app->get('/user/index', UserController::class . ':index')->add($requireLogin);
↓以下の感じに直す
//classを1ファイルで作成
<?php
class RequireLoginMiddleware
{
public function __construct($db)
{
//
}
public function __invoke(Request $request, RequestHandler $handler): Response
{
//処理
}
}
//インスタンスをaddする
//引数を渡すときはコンストラクタに渡して保持してもらう。
$app->get('/user/index', UserController::class . ':index')->add(new RequireLoginMiddleware());
エラー1
Uncaught TypeError: Slim\Handlers\Strategies\RequestResponse::__invoke(): Return value must be of type Psr\Http\Message\ResponseInterface, null
controllerの中でresponseを明確にreturnしないと上記エラーがでるようになった。middlewareの影響かも。各所にreturn $response;を追加。
エラーハンドリングの修正
dependencies.phpで設定していたエラーハンドラはCustomErrorHandlerとして別ファイルに外だし。
index.phpの中で設定を追加。
参考https://codezine.jp/article/detail/12397?p=3
class CustomErrorRenderer implements ErrorRendererInterface
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function __invoke(Throwable $exception, bool $displayErrorDetails): string
{
$msg =[];
if($exception instanceof HttpNotFoundException) {
$msg = ['message' => 'Not Found'];
}elseif($exception instanceof HttpMethodNotAllowedException) {
$msg = ['message' => 'Method Not Allowed'];
}else{
$msg =['message' => 'Internal Server Error'];
}
return json_encode($msg);
}
}
# index.php
$app = AppFactory::create();
// 以下追加
$app->addRoutingMiddleware();
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->forceContentType('application/json');
$errorHandler->registerErrorRenderer('application/json', CustomErrorRenderer::class);
UnitTestの修正
-
settingやcontainer周りはindex.phpと同じように修正。
-
responseの取得をprocessからhandleに変更
$response = $app->process($request, $response);
↓
$response = $app->handle($request);
-Request::createFromEnvironment($environment);
が使えなくなったので、自前でcreateRequst()を追加。
参考
https://github.com/slimphp/Slim-Skeleton/blob/master/tests/TestCase.php#L68
https://discourse.slimframework.com/t/migrating-from-slim-3-to-4-writing-php-unit-tests/4193/2
- 合わせてgetのquery parameterの渡し方の変更が必要になった。URLに?+クエリーをそのままつけていたが、?がついているとエスケープされて404になってしまう。以下のように修正。
$request =$request->withQueryParams(['key'=> 'value']);