SHOEISHA iD

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

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

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

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

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

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

 本連載では軽量PHPフレームワークであるSlimを紹介していきます。フレームワークと言えば、重厚長大なもの、いわゆるフルスタックフレームワークが多い中で、あえて軽量フレームワークを取り上げます。軽量ゆえのメリットを味わっていただこうと思います。前回は、当初の予定を変更して、リリースされた最新バージョンであるSlimバージョン4にアップグレードする方法を紹介しました。今回は、そのバージョン4でSlim内での重要度がより増したミドルウェアを紹介します。

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

リクエスト処理の前後に処理を挿入できるミドルウェア

 ミドルウェアは、一言でいうと、リクエスト処理の前後に処理を挿入できる仕組み、となります。そのミドルウェアの概論については、拙記事「Laravelにおけるミドルウェアを理解しよう」で解説を行っています。LaravelでもSlimでも、ミドルウェアの概念は同じなので、一読いただければ幸いです。ここでは、概論よりも、実際のコードを使ってSlimのミドルウェアを体感していただこうと思います。

Slimのミドルウェアは1つのクラス

 ミドルウェアは上述のように、リクエスト処理の前後に処理を挿入できる仕組みです。その挿入したい処理を、Slimでは1つのクラスとして記述します。それは、リスト1のようなコードとなります。

[リスト1]firstslim/src/classes/middlewares/BeforeHelloMiddleware.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 BeforeHelloMiddleware implements MiddlewareInterface  // (1)
{
	public function process(Request $request, RequestHandlerInterface $handler): Response  // (2)
	{
		print("BeforeHelloMiddlewareからHello!<br>");  // (3)
		$response = $handler->handle($request);  // (4)
		return $response;  // (5)
	}
}

 ミドルウェアの処理を記述したクラス(ミドルウェアクラス)のクラス名、格納先フォルダは特に規定が無いので、自由に決めることができます。とはいえ、ミドルウェアクラスであることがすぐに分かるためにも、リスト1のように、「○○Middleware」といったクラス名にし、/classes/middlewaresフォルダのように1つのフォルダ内にまとめて格納した方が、管理が楽になります。

 一方、クラスの作り方には決まりがあります。それは、リスト1の(1)のように、\Psr\Http\Server\MiddlewareInterfaceを実装(implements)する必要があるということです。このインターフェースには、以下の構文のメソッドが1つ定義されています。

[構文]MiddlewareInterfaceに定義されたメソッド
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface

 このprocess()メソッド内にリクエスト処理の前後に挿入したい処理を記述します。リスト1では(2)が該当します。

 メソッド内の記述は、リスト1では3行記述されています。(3)は画面に文字列を表示する処理です。(4)はコードの通り、process()メソッドの第2引数であるRequestHandlerInterfaceのメソッドhandle()を実行し、そのhandle()メソッドの戻り値として返ってくるレスポンスオブジェクトを受け取ります。そして、それを(5)でprocess()メソッドの戻り値としてリターンしています。この(4)の処理については、のちに詳しく解説します。

ミドルウェアの登録はルーティング登録に続けてadd()メソッドを記述する

 ミドルウェアクラスが作成できたところで、このクラスをリクエスト処理に挿入していきましょう。まず、リクエスト処理の本体となるコントローラクラスとして、リスト2のChap8Controller.phpファイルを作成します。

[リスト2]firstslim/src/classes/controllers/Chap8Controller.php
<?php
namespace CodeZineSlim\FirstSlim\controllers;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class Chap8Controller
{
	public function mainRequest(Request $request, Response $response, array $args): Response
	{
		print("ここはメインのリクエスト処理<br>");
		return $response;
	}	
}

 ミドルウェアクラスの動きを理解しやすいように、リクエスト処理であるmainRequest()メソッドには、画面に「ここはメインのリクエスト処理」と表示するシンプルな処理しか含まれていません。

 次に、このリクエスト処理をルーティング登録します。実は、ミドルウェアを利用する場合、このルーティング登録と同時に登録するようになっています。それはリスト3のコードです。

[リスト3]firstslim/src/routes8.php
<?php
use CodeZineSlim\FirstSlim\controllers\Chap8Controller;
use CodeZineSlim\FirstSlim\middlewares\BeforeHelloMiddleware;

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

 リスト3の(1)では、ルーティング登録メソッドany()を使って、ルーティングパターン/no8/withBeforeMiddlewareでリスト2のmainRequest()メソッドを登録しています。その続きとしてadd()メソッドを実行し、引数としてリスト1で用意したミドルウェアクラスをnewして渡しています。これがミドルウェアの登録コードです。ここでは、ルーティング登録メソッドとしてany()を使っていますが、他のルーティング登録メソッドでも同様です。any()を例に構文としてまとめると以下の通りになります。

[構文]ルーティングでのミドルウェア登録
$app->any(…)->add(new ミドルウェアクラス);

 最後に、routes8.phpをindex.phpで読み込むコードを記述し、動作確認を行っておきましょう。リスト4の太字の1行を追記してください。

[リスト4]firstslim/src/public/index.php
<?php
〜省略〜
require_once("../routes8.php");
$app->run();

 追記が終了したら、以下のURLにアクセスしてください。

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

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

図1:ミドルウェアの処理が挿入された実行画面
図1:ミドルウェアの処理が挿入された実行画面

 図1を見ると、2行目に表示された内容は、リクエスト処理であるmainRequest()メソッドの実行結果です。一方、1行目はmainRequest()メソッドには含まれておらず、これこそがまさにミドルウェアクラスであるリスト1の(3)の処理であり、リクエスト処理の前に処理が挿入されたことが理解できます。

 このように、各リクエスト処理の前後に定型処理を挿入したい時、その処理をミドルウェアクラスとして作成すると、ルーティング登録時に登録するだけで済みます。全てのコントローラクラスメソッド内に定型処理を記述する必要が無くなります。

次のページ
前後の区別とhandle()メソッドの働き

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

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

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー

アクセスランキング

アクセスランキング