リクエストとレスポンスとビューについて
次に、リクエスト処理のリクエストオブジェクトとレスポンスオブジェクトについて見ていきましょう。
リクエスト処理の引数がPSR-7準拠に変更
ルーティング登録コールバック関数にしても、コントローラクラスメソッドにしても、第1引数である$requestは型指定として\Psr\Http\Message\ServerRequestInterfaceとなっており、これは、PSR-7で定義されたインターフェースです。同様に第2引数である$responseもPSR-7で定義されている\Psr\Http\Message\ResponseInterfaceです。
Slimのv3でも、引数の型としてはPSR-7に準拠しているように見えます。しかし、その実、PSR-7のインターフェースを実装したSlimの独自クラスが使われていました。そのため、例えば、第4回「SlimでJSONデータを送信する方法」で紹介したリスト1の(3)では次のようなメソッドが利用されています。
$response->withJson($jsonArray);
実は、このwithJson()メソッドはPSR-7のResponseInterfaceには定義されていないメソッドであり、Slimのレスポンスクラス独自のメソッドといえます。
一方、v4では、この引数がPSR-7に完全準拠するようになりました。そのため、Slim独自のリクエストクラス、および、レスポンスクラスは廃止されています。その代わり、PSR-7を実装したクラス群ならばどれでも利用できるような自由度を持たせています。もし、特に指定がない場合は、Slimで用意されたPSR-7実装のパッケージを利用すればよく、それが、slim/psr7です。これが、変更点4の内容です。
なお、PSR-7準拠のクラス群でJSONレスポンスを返すコードは次のようになります。
$returnJson = json_encode($jsonArray);
$response->getBody()->write($returnJson);
return $response->withHeader("Content-Type", "application/json");
これが、PSR-7に準拠したJSONレスポンスの返し方です。
Twigインスタンスの取得もcreate()メソッドに変更
レスポンスに関してもう1つ変更点があります。それは、Twigの利用です。SlimでTwigを利用するためのライブラリであるTwig-Viewもメジャーアップデートされており、Twigインスタンスの取得方法が変わっています。例えば、第4回「テンプレートエンジンTwigと連携させてみる」のリスト4の(2)でTwigインスタンスを取得するコードとして次のものを記述しています。
$view = new Twig("../templates");
単純にnewしているだけですが、これが、Slim v4に対応したTwig-View v3では次のようにstaticメソッドであるcreate()を利用してインスタンスを取得するように変更になっています。
$view = Twig::create("../templates");
コンテナが別ライブラリに切り離された
第5回で紹介したように、Slimのv3では、内部にDIコンテナが内包されていました。これが、v4から切り離されました。これが変更点の5です。具体的に見ていきましょう。
DIコンテナは別パッケージを利用
第5回「コンテナとその使い方の基本」のリスト1の(1)で次のようなコードが記載されています。
$container = $app->getContainer();
Slimのv3までは、このようにAppインスタンスが生成されたら、自動的に内部にDIコンテナが生成されており、getContainer()メソッドでそのコンテナを取得し、それに対して登録などの操作が行えました。
これが、v4からは切り離されて、Slim本体に内包されなくなりました。代わりに、先のリクエストとレスポンスに関するクラス群と同様の考え方を採用し、PSR-11を実装したライブラリならばどれを利用してもよくなりました。そのPSR-11実装ライブラリの例として、Slimの解説ページではPHP-DIが紹介されています。
そこで、まず、このPHP-DIが利用できるように、次のコマンドを実行し、requireしておきましょう。
composer require php-di/php-di
コンテナへの登録はAppインスタンス取得前
コンテナがSlimの本体から切り離されたことで、コンテナへの登録コードも変更になっています。v3では、第5回「コンテナとその使い方の基本」のリスト1の(1)のように、Appインスタンスからコンテナインスタンスを取得して、それに登録を行っていましたが、これが、次のようなコードに変わります。
<?php
use DI\Container; // (1)
〜省略〜
require_once("../vendor/autoload.php");
$container = new Container(); // (2)
$container->set("view", function($container) { // (3)
$view = Twig::create("../templates"); // (4)
return $view;
});
$container->set("logger", function($container) {
$logger = new Logger("firstslim");
$fileHandler = new StreamHandler("../../logs/app.log");
$logger->pushHandler($fileHandler);
return $logger;
});
AppFactory::setContainer($container); // (5)
$app = AppFactory::create();
〜省略〜
PHP-DIによるコンテナの本体クラスは\DI\Containerです。このインスタンスを手動で生成する必要があります。といってもnewするだけですので、事前にリスト3の(1)のようにuseしておき、(2)でnewします。
このようにして生成されたContainerインスタンスに対して、各種インスタンス生成処理を登録したのち、これを、Slim側に渡してあげます。したがって、v3では、Appインスタンスを生成した後にコンテナインスタンスを取得していましたが、v4ではAppインスタンスの生成よりも先にコンテナインスタンスを生成し、コンテナへの登録処理を行った後、(5)のように、SlimのAppFactoryに登録します。この時に利用するメソッドがsetContainer()です。
コンテナへの登録処理はset()メソッドを利用
newにより生成されたコンテナインスタンスに対して、各種インスタンス生成処理の登録については、v3では、第5回「コンテナとその使い方の基本」のリスト1の(2)にあるように、次のような連想配列への格納処理のようなコードが記述できていました。
$container["view"] = function($container) {
:
};
この方法は、PHP-DIを利用する場合は使えません。代わりにリスト3の(3)のようにset()メソッドを利用します。第1引数がインスタンス名、第2引数がインスタンスを生成するコールバック関数です。
コールバック関数内の記述は、v3の時と同様に行えます。ただし、リスト3の(4)でのTwigインスタンスの生成に関しては、Twig-Viewのメジャーアップデートに伴って、create()メソッドに変更しています。
コンテナからインスタンスの取得はget()メソッド一択
コンテナへの登録処理がset()メソッドを利用するようになったのと同様に、コンテナからインスタンスの取得処理もget()メソッドのみとなりました。例えば、第5回「コンテナとその使い方の基本」のリスト2の(1)にある次のコードは問題なく動作します。
$view = $this->get("view");
一方、同回「コンテナの仕組みに関する少し難しい話」で紹介した次の配列アクセスのコードは利用できません。
$view = $this["view"];
同様に、次のプロパティのようなアクセスもできなくなっています。
$view = $this->view;
まとめ
今回は、予定を変更して、メジャーアップデートされたSlim v4について、v3からの変更点を中心に紹介しました。それに伴って、これまで紹介してきたサンプルをどう改変したら動作するようになるかについても触れてきました。
なお、第6回については全く触れていません。これは、ここまで紹介してきた内容の変更を反映していれば、コントローラクラスについては特に変更は不要だからです。
次回は、ミドルウェアについて紹介します。変更点6で紹介したように、Slim v4では、ルーティング処理やエラーハンドラなどさまざまなものがミドルウェアとして実行されるようになりました。そのため、ミドルウェアの理解はSlimをより深く理解するためには不可欠です。ご期待ください。
