Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

ルーティング処理をまとめた、Slimのコントローラクラスを使ってみよう

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

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2019/10/09 11:00

 本連載では軽量PHPフレームワークであるSlimを紹介していきます。フレームワークといえば、重厚長大なもの、いわゆるフルスタックフレームワークが多い中で、あえて軽量フレームワークを取り上げます。軽量ゆえのメリットを味わっていただこうと思います。前回は、アプリ内で使われる各種インスタンスの生成を管理してくれるコンテナ機能とコンテナを利用することで可能となるDIという考え方を紹介しました。今回は今までコールバック関数内に記述していた処理をクラスとしてまとめるコントローラクラスを紹介します。

目次

1処理1クラスのコントローラクラス

 前回までのサンプルでは、アプリにアクセスしてきたときの処理(これをリクエスト処理と言います)をルーティングコールバック関数内に記述していました。その問題点の確認から行いましょう。

ルーティングコールバック関数の問題点

 各リクエスト処理をルーティングコールバック関数に記述していくと、ソースコードの見通しが悪くなるという問題が生じます。本連載中に紹介したソースコードは、あくまでサンプルですので、大したコード量ではありません。

 それでも、ルーティング登録ファイル内のソースコードの見通しがいいとは言えません。ましてや、本運用で使われるアプリとなると、各リクエスト処理のコード量はサンプルの比ではなく、ルーティング登録ファイル内はさらにコードの見通しが悪くなり、メンテナンス性が極端に下がります。

 これを解決するには、ルーティング登録のコードとリクエスト処理のコードを分離することです。

コントローラクラス

 そこで、Slimでは、リクエスト処理をクラスとして記述し、それをルーティング登録する方法が用意されています。そういったリクエスト処理が記述されたクラスのことを、「コントローラクラス」と言います。そのうちで、1つのリクエスト処理を1つのクラスとして記述する方法をまず紹介します。

 では、実際に作成していきましょう。まず、コントローラクラスファイルを格納するフォルダを作ります。こういった自作クラスファイル類を格納するフォルダについて、Slimでの取り決め事項は特にありません。

 そこで、srcフォルダ直下にそういうクラス類をまとめて入れておくフォルダとしてclassesフォルダを作成します。このフォルダ以下のサブフォルダはそれぞれクラスの役割ごとに作ります。コントローラクラス類は、controllersフォルダに格納することにします。さらに、その中に階層構造を作成して整理します。今回は第6回にあたるので、サブフォルダとしてno6を作成し、その中にリスト1のHelloControllerクラスを作成してください。

[リスト1]firstslim/src/classes/controllers/no6/HelloController.php
<?php
namespace CodeZineSlim\FirstSlim\controllers\no6;  // (1)

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

class HelloController
{
	//Slimのコンテナインスタンスを格納するプロパティ。
	private $container;  // (2)
	//コンストラクタ。
	public function __construct(ContainerInterface $container)  // (3)
	{
		$this->container = $container;
	}
	//実際に実行されるメソッド。
	public function __invoke(Request $request, Response $response, array $args): Response  // (4)
	{
		$view = $this->container->get("view");  // (5)
		return $view->render($response, "hello.html");  // (6) 
	}
}

 リスト1では、(5)と(6)が実際のリクエスト処理であり、ここでは前回のリスト2と同じ処理を行うように記述しています((5)が前回のリスト2と違いますが、こちらは後述します)。そのようなリクエスト処理1つ分を1つのクラスとして記述する場合は、リスト1の(4)のようにリクエスト処理をマジックメソッド__invoke()に記述したクラスを作成します(※)。

 __invoke()メソッドの引数は、コールバック関数の引数と同じものを記述し、順番に、ServerRequestInterfaceインスタンス($request)、ResponseInterfaceインスタンス($response)、ルーティングプレースホルダが格納された連想配列($args)です。戻り値についても、コールバック関数と同じで、ResponseInterfaceインスタンスをリターンします。

 なお、クラス名については特に指定はないので自由につけてもらってもかまいませんが、どういった処理を行うコントローラクラスなのかわかるようにしておいた方がいいでしょう。おすすめは、「〇〇Controller」といったネーミングにすることです。

 また、このクラスの名前空間も、classesフォルダ以降のフォルダ階層と同じ階層構造にしておけば、ベンダプレフィックスは何でもいいです。リスト1では(1)のように、実際のフォルダ構成であるcontrollers\no6の前に、プレフィックスとしてCodeZineSlim\FirstSlimとしています。これについては、もう一度後で触れます。

※マジックメソッドとは何か、__invoke()メソッドがどのようなメソッドかについては、拙記事「PHPの「マジックメソッド」とは――「__set()」「__get()」「__invoke()」の使い方」を参照してください。

コントローラクラスのコンストラクタ

 ここで、リスト1の(5)のコードに注目します。前回のリスト2ではこの行は以下のコードでした。

$view = $this->get("view");

 その際、解説したように、ルーティングコールバック関数内では、$thisという変数はSlimのコンテナそのものを表します。一方、コントローラクラスでは$thisはコントローラクラスのインスタンスを表すので、当然コンテナとは違い、上の記述はできません。

 では、コントローラクラスでコンテナを扱いたい場合はどうすればいいのでしょうか。そこで登場するのがコンストラクタです。コントロールクラスにコンストラクタを記述し、その引数として、コンテナを表すContainerInterface型引数($container)を定義しておきます。

 すると、Slimがこのコントローラクラスを呼び出して実行する際にコンストラクタの引数に自動的にコンテナが渡されるようになります。つまり、リスト1の(3)の引数$containerはコンテナインスタンスを表します。これを(2)のプロパティに格納しておくことで、このコントローラクラス中ではいつでもコンテナが利用できるような仕組みとなるのです。

 リスト1の(5)ではこのプロパティのコンテナからget()メソッドを使ってTwigインスタンスを取得しています。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

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

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きた...

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

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:軽量PHPフレームワークSlimを習得しよう
All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5