SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

軽量PHPフレームワークSlimを習得しよう

リクエスト処理の前後に処理を挿入できる、Slimのミドルウェアを使ってみよう

軽量PHPフレームワークSlimを習得しよう 第8回

  • X ポスト
  • このエントリーをはてなブックマークに追加

前後の区別とhandle()メソッドの働き

 前節で紹介したサンプルでは、リクエスト処理の前に処理が挿入されました。ここまで再三述べているように、ミドルウェアはリクエスト処理の「前後」に処理が挿入できます。「後」の場合について見ていきましょう。

前後の区別はhandle()メソッドの記述位置で決まる

 リクエスト処理の後に処理を挿入したい場合のミドルウェアクラスのコードは、リスト5の通りになります。

[リスト5]firstslim/src/classes/middlewares/AfterHelloMiddleware.php
<?php
namespace CodeZineSlim\FirstSlim\middlewares;

use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class AfterHelloMiddleware implements MiddlewareInterface
{
	public function process(Request $request, RequestHandlerInterface $handler): Response
	{
		$response = $handler->handle($request);  // (1)
		print("AfterHelloMiddlewareからHello!<br>");  // (2)
		return $response;
	}
}

 リスト1との違いは、クラス名と(1)と(2)のコードだけです。その(1)と(2)も表示文字列は少し違っているぐらいで、大きな違いはその順序です。リスト1のBeforeHelloMiddlewareでは、handle()の前にprint()を実行しています。一方、リスト5では、handle()の後にprint()を実行しています。

 実は、このhandle()メソッドとはリクエスト処理本体を指し、リスト1のように、handle()の前に挿入したい処理を記述することで、リクエスト処理の前に処理が挿入され、同様に、リスト5のように、handle()の後に記述することで、リクエスト処理の後に処理が挿入される仕組みとなっているのです。

 では、このミドルウェアを利用するルーティング登録を行い、動作確認を行っておきましょう。リクエスト処理としては、リスト2のmainRequest()を再利用します。routes8.phpにリスト6の太字の行を追記してください。

[リスト6]firstslim/src/routes8.php
〜省略〜
use CodeZineSlim\FirstSlim\middlewares\AfterHelloMiddleware;

$app->any("/no8/withBeforeMiddleware", Chap8Controller::class.":mainRequest")->add(new BeforeHelloMiddleware());
$app->any("/no8/withAfterMiddleware", Chap8Controller::class.":mainRequest")->add(new AfterHelloMiddleware());

 追記ができたら動作確認を行っておきましょう。以下のURLにアクセスしてください。

  • http://localhost/firstslim/src/public/no8/withAfterMiddleware

 図2の画面が表示されます。

図2:リクエスト処理の後に処理が挿入された実行画面
図2:リクエスト処理の後に処理が挿入された実行画面

 図2から分かるように、リクエスト処理の後にミドルウェアの処理が無事、挿入されています。

handle()の記述位置で自由に決められる挿入位置

 前項では、handle()メソッドと挿入する処理の位置関係で、リクエスト処理の前後どちらに挿入するかが決まることが分かりました。勘のいい人はすでに気づいているかもしれませんが、実はSlimのミドルウェアは、handle()の記述位置でリクエスト処理の位置を決められるため、リクエスト処理の前後どちらかではなく、そのどちらにも自由に挿入できるようになっています。

 例えば、リスト7のようなコードです。

[リスト7]firstslim/src/classes/middlewares/InnerMiddleware.php
<?php
namespace CodeZineSlim\FirstSlim\middlewares;

use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class InnerMiddleware implements MiddlewareInterface
{
	public function process(Request $request, RequestHandlerInterface $handler): Response
	{
		print("InnerMiddlewareのhandle()の前の処理<br>");  // (1)
		$response = $handler->handle($request);  // (2)
		print("InnerMiddlewareのhandle()の後の処理<br>");  // (3)
		return $response;
	}
}

 リスト7では、(2)のhandle()メソッドの呼び出しの前に(1)の文字列表示、後に(3)の文字列表示と、リクエスト処理の前後両方に処理を記述しています。実際に、リクエスト処理の前後に処理が挿入されるか動作確認をしておきましょう。routes8.phpにリスト8の太字の行を追記してください。

[リスト8]firstslim/src/routes8.php
〜省略〜
use CodeZineSlim\FirstSlim\middlewares\InnerMiddleware;
〜省略〜
$app->any("/no8/withBeforeMiddleware", Chap8Controller::class.":mainRequest")->add(new AfterHelloMiddleware());
$app->any("/no8/withInnerMiddleware", Chap8Controller::class.":mainRequest")->add(new InnerMiddleware());

 追記ができたら動作確認を行っておきましょう。以下のURLにアクセスしてください。

  • http://localhost/firstslim/src/public/no8/withInnerMiddleware

 図3の画面が表示されます。

図3:リクエスト処理の前後両方に処理が挿入された実行画面
図3:リクエスト処理の前後両方に処理が挿入された実行画面

 このように、Slimのミドルウェアは、リクエスト処理の前後両方に処理を挿入できる仕組みとなっているので、イメージ的には図4の通り、リクエスト処理を中心にした同心円のような仕組みとなっています。

図4:Slimのミドルウェアは同心円のイメージ
図4:Slimのミドルウェアは同心円のイメージ

複数重ねられるミドルウェア

 さらに、このミドルウェアは複数重ねることができます。例えば、リスト9のようなミドルウェアを考えます。なお、リスト9の内容は、リスト7のInnerMiddleware.phpとほぼ同じです。違いは、太字の部分だけです。

[リスト9]firstslim/src/classes/middlewares/OuterMiddleware.php
<?php
namespace CodeZineSlim\FirstSlim\middlewares;

use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class OuterMiddleware implements MiddlewareInterface
{
	public function process(Request $request, RequestHandlerInterface $handler): Response
	{
		print("OuterMiddlewareのhandle()の前の処理<br>");
		$response = $handler->handle($request);
		print("OuterMiddlewareのhandle()の後の処理<br>");
		return $response;
	}
}

 このOuterMiddlewareとリスト7のInnerMiddlewareの両方をリクエスト処理に付与してみましょう。ルーティング登録コードは次の通りになります。routes8.phpにリスト10の太字の行を追記してください。

[リスト10]firstslim/src/routes8.php
〜省略〜
use CodeZineSlim\FirstSlim\middlewares\OuterMiddleware;
〜省略〜
$app->any("/no8/withInnerMiddleware", Chap8Controller::class.":mainRequest")->add(new InnerMiddleware());
$app->any("/no8/withDoubleMiddleware", Chap8Controller::class.":mainRequest")->add(new InnerMiddleware())->add(new OuterMiddleware());  // (1)

 追記ができたら動作確認を行っておきましょう。以下のURLにアクセスしてください。

  • http://localhost/firstslim/src/public/no8/withDoubleMiddleware

 図5の画面が表示されます。

図5:ミドルウェアを2個付与した実行画面
図5:ミドルウェアを2個付与した実行画面

 ミドルウェアを複数付与するには、リスト10の(1)のように、add()メソッドを続けて複数実行するだけです。その際、注意しておく必要があるのは、その追加の順番です。ここでの処理の流れを図にすると、図6の通りになります。

図6:複数ミドルウェアも同心円が重なるイメージ
図6:複数ミドルウェアも同心円が重なるイメージ

 図6でSlimのミドルウェアは同心円のイメージであると伝えましたが、複数ミドルウェアを付与した場合も同心円が重なるイメージを持ってください。その際、リクエスト処理を中心に、add()した順番で円が重なります。そのため、以下の順番で処理が行われます。

 最後にadd()したOuterのhandle()より前の処理
 ↓
 最初にadd()したInnerのhandle()より前の処理
 ↓
 リクエスト処理
 ↓
 最初にadd()したInnerのhandle()より後の処理
 ↓

 最後にadd()したOuterのhandle()より後の処理

 図6の実行結果もそのことを物語っています。

次のページ
ミドルウェア登録のバリエーション

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
軽量PHPフレームワークSlimを習得しよう連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook<個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/12263 2020/05/19 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング