SHOEISHA iD

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

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

Zend Framework入門

Zend Framework入門(3):PHPでMVCアプリケーションを構築しよう - Zend_Controller(前編) -

Zend Frameworkによる実践的なPHPアプリケーション開発 3

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

フロントコントローラ

 リクエストを受け取ったフロントコントローラ内では、まず受け取ったURIが解析され、最初に呼び出されるべきコントローラ名/アクション名/各種リクエストパラメータが取り出されます。この過程が「ルーティング」で、ルーティングを行うのがルータと呼ばれるものです。ルータによる出力はリクエストオブジェクトに格納され、ディスパッチャ(ディスパッチを行うための仕組み)に送られます。

 ディスパッチャではリクエストオブジェクトに格納されているコントローラ名/アクション名/リクエストパラメータなどの情報を展開し、該当するアクションコントローラのインスタンスを作成して、最終的にアクションコントローラをコールします。

 ルータとディスパッチャのどちらにおいてもコントローラ名/アクション名/リクエストパラメータが取り出されていますが、ルーティングは最初に1回だけ行われ、送られてきたリクエストURIの解析を行うものなのに対し、ディスパッチの方は送られてきたリクエストオブジェクトからの情報の展開を行います。つまり、URI解析(ルーティング)以降、リクエストオブジェクトに格納されている情報に対し何らかの操作がなされた場合には、それを読み込んで新たなコントローラ名/アクション名/リクエストパラメータを得るのはルータではなくディスパッチャだということです。

フロントコントローラにおける各処理の実際の記述

 前回サンプルのフロントコントローラで使っていた「->run()」は、下記を見ると分かるように3つの処理を行っています。

Zend/Controller/Front.php内のrun()の定義
public static function run($controllerDirectory)
{
    self::getInstance()
        ->setControllerDirectory($controllerDirectory)
        ->dispatch();
}

 カスタマイズを特に行う必要がない場合はこちらの方が便利ですが、コントローラフォルダやオブジェクトなどを設定したい場合は、各処理を個別に記述する必要があるでしょう。

 実際に個別の処理をフロントコントローラで記述すると次のようになります。

front controller
<?php
require_once 'Zend/Controller/Front.php';
$front=Zend_Controller_Front::getInstance();
$front->setControllerDirectory('../application/controllers');
$front->dispatch();

 各々の処理について解説していきます。

フロントコントローラのインスタンスを取得する「::getInstance()」

Zend_Controller_Frontインスタンスの取得
<?php
$front = Zend_Controller_Front::getInstance();

 まず、フロントコントローラを利用するためにインスタンスを取得する必要があります。このインスタンスは一つしか存在しないことになっています。これをシングルトンパターンといい、アプリケーションの総元締めとも言えるフロントコントローラの性格に合致したものとなっています。

コントローラフォルダを指定する「->setControllerDirectory()」

コントローラフォルダの指定
<?php
$front->setControllerDirectory('../application/controllers');

 次に、アクションコントローラが格納されているフォルダを指定します。ここは配列を使用することで複数指定できます。また、既にコントローラフォルダが指定されているところへ新たに後から「->addControllerDirectory()」で追加することも可能です。これらについては次回解説予定です。

モジュールについて
 Zend Frameworkでは、個々のMVCアプリケーションを「モジュール」として扱うことができます。詳細は次回解説予定ですが、こうすることで複数のMVCアプリケーションを配置することができるようになります。上記の「->setControllerDirectory()(あるいは->addControllerDirectory())」で複数のフォルダを指定するというのは、このような時に役立ちます。

ディスパッチを行う「->dispatch()」

ディスパッチを行う
<?php
$front->dispatch();

 フロントコントーラのインスタンスが取得され、コントローラフォルダも決まると、後はディスパッチを行うのみです。

ルーティングはどこで行われる?
 上記の3つの処理中、ルーティングはどこで行われているのでしょうか。実は「->dispatch()」でルーティングとディスパッチ、さらには(ビューのレンダリングを行うかどうかは別として)レスポンスを返すところまでを行っています。

 「->dispatch()」ではリクエストオブジェクト/レスポンスオブジェクトを指定することができます。これはアプリケーションの開発過程において、単体テストで独自にリクエストを作成してアプリケーションの流れをテストするなどの場合に有用です。

<?php
$front->dispatch(<リクエストオブジェクト>,<レスポンスオブジェクト>);

 デフォルトはnullで、その場合、ディスパッチャはそれまでに登録されているリクエストオブジェクト/レスポンスオブジェクトを探し、それをディスパッチに使用します。なければその場でデフォルトのオブジェクトを作成し、ディスパッチに使用します。

レスポンスオブジェクト
 レスポンスオブジェクトはリクエストオブジェクトと対になる存在で、コンテンツやヘッダーを収集して返す役割を持ちます。詳細はビューの回で解説予定です。

ディスパッチについて

 ここでディスパッチについて詳しく見ていきましょう。

ディスパッチの過程

 ディスパッチの過程においては、以下の順序で処理が行われています。

  1. 情報を展開:
  2. リクエストオブジェクトに格納されているコントローラ名/アクション名/リクエストパラメータなどの情報が展開され、該当するアクションコントローラを決定する
  3. インスタンスを作成:
  4. 該当するアクションコントローラのインスタンスを作成する
  5. 実際にコール:
  6. インスタンスの作成を完了すると、実際にアクションコントローラに含まれるアクションメソッドをコールする

リクエストの再処理

 ルータからリクエストオブジェクトを受け取ると、ディスパッチャは「リクエストが然るべきアクションに受け渡された」ことを示すフラグをセットします。このフラグはアクションコントローラや「preDispatch()」「postDispatch()」からリセットすることができます(後述)。

ディスパッチャのクラスについて

 デフォルトでディスパッチャとして使用されるのはZend_Controller_Dispatcher_Standardです。これは抽象クラスZend_Controller_Dispatcher_Abstractを継承しています。もしアクションコントローラやアクションメソッドの命名規則を変える等、ディスパッチャの仕様を変更したい場合には、Zend_Controller_Dispatcher_Abstractを継承しディスパッチャのサブクラスを作成することとなります。

環境にアクセスするためのメソッド

 その他フロントコントローラでは、リクエスト処理中各環境にアクセスするためのメソッドが揃っています。以下の表に示します。

デフォルトの指定

メソッド概要
(set|get)DefaultControllerName()コントローラ名のデフォルト(index)を指定/現設定を取得
(set|get)DefaultAction()アクション名のデフォルト(index)を指定/取得
(set|get)BaseUrl()ルーティング時にURLから取り除く基底URLを指定/取得

サブクラスを使用する際など、クラスも含めた各オブジェクトの指定

メソッド概要
(set|get)Request()ディスパッチに用いるリクエスト・オブジェクトの指定/取得
(set|get)Router()ディスパッチに用いるルータ・オブジェクトの指定/取得
(set|get)Dispatcher()ディスパッチに用いるディスパッチャ・オブジェクトを指定/取得
(set|get)Response()ディスパッチに用いるレスポンス・オブジェクトを指定/取得

プラグイン使用関連

メソッド概要
registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)プラグインオブジェクトを登録
unregisterPlugin($plugin)プラグインオブジェクトを登録解除

例外発生処理関連

メソッド概要
throwExceptions($flag)ディスパッチ時発生した例外のスローの有無を切り替え
returnResponse($flag)フロントコントローラがdispatch()からのレスポンスを返す(true)かレスポンスを自動的に発行する(false)かを切り替え。デフォルトはfalse。レスポンスの発行前に内容をチェックしたりログを取りたい場合などにtrueに設定する

その他

メソッド概要
resetInstance()現在の設定を消去。主にテストに用いる

パラメータをセットする

 前回紹介した通り、フロントコントローラではパラメータをセットすることができます。これによりフロントコントローラにアプリケーションの設定情報を持たせてルータ/ディスパッチャ/アクションコントローラ内で使用することができます。ここで前回挙げたパラメータを扱うためのメソッドを再掲しておきます。

フロントコントローラでパラメータを扱うためのメソッド
メソッド内容
setParam($name, $value)パラメータ$nameの値を$valueに設定する
getParam($name)パラメータ$nameの値を得る
setParams(array $params)連想配列$paramsにより複数のパラメータを設定する
getParams()すべてのパラメータの一覧を得る
clearParams($name)$nameを消去する

 ただし、ディスパッチの過程で使用するために事前に定義されているパラメータがあります。以下の表に示します。

事前に定義されているパラメータ
パラメータ内容
disableOutputBufferingtrueにするとディスパッチャが出力をバッファリングせず、その場でレスポンスを行う。通常はfalse。一旦バッファリングしてから出力することで、必ずヘッダー部分が先に出力されるようになっている
noErrorHandler例外処理を独自に行いたい場合など、trueで「ErrorHandler」プラグインを無効にする(ErrorHandlerについては後述)
noViewRendererXMLやJSONなどHTML以外の出力をしたい場合や出力の必要がない場合など、trueで「ViewRenderer」アクションヘルパーを無効にする(Zend_Viewの回でも解説予定)
useDefaultControllerAlwaystrueで指定されたモジュール/コントローラ/アクションが存在しないリクエストのディスパッチ先をデフォルトコントローラにする(後述のエラーコントローラはそれ以外の例外処理にも適用される)

サンプル

 ここでちょっとしたサンプルを紹介します。フロントコントローラでデフォルトのコントローラ名とアクション名をそれぞれ「wings」「codezine」に変えてみます。

index.php
<?php
require_once 'Zend/Controller/Front.php';
$front=Zend_Controller_Front::getInstance();
$front->setControllerDirectory('../zendapps/controllers');

$front->setDefaultControllerName('wings');
$front->setDefaultAction('codezine');

$front->dispatch();

 「setDefaultControllerName('wings')」と「setDefaultAction('codezine');」でデフォルトのコントローラ名とアクション名を変えています。

 もちろん、コントローラファイルは「WingsController.php」を用意します。「IndexController.php」は必要ありません。

WingsController.php
<?php
require_once 'Zend/Controller/Action.php';
require_once 'Zend/Date.php'; //Zend_Dateコンポーネントの呼び出し

class WingsController extends Zend_Controller_Action
{
    public function codezineAction()
    {
        $date=new Zend_Date;  // (1)
        $this->view->assign('dt', $date->get(Zend_Date::TIMES));  // (2)
    }
}

 アクション・メソッドも「indexAction」はなく、「codezineAction」を定義しています。また、「codezineAction」中でビューに時刻を送るよう指定しています。ファイルの冒頭で呼び出している「Zend_Date」コンポーネントは日付・時刻を処理するためのコンポーネントで、(1) (2)で現在の時刻を取得しています(詳しくはZend_Dateの回で解説予定です)。ビューは「views/scripts/wings/codezine.phtml」を用意します。

 以上で、「http://localhost」にアクセスするだけで「wings」アクションコントローラの「codezine」アクションメソッドが呼び出され、時刻が表示されているのが分かると思います。

サンプルの実行結果
サンプルの実行結果
 以降のサンプルでは、「index.php」の
$front->setDefaultControllerName('wings');
$front->setDefaultAction('codezine');
 はコメントアウトしてください。

次のページ
アクションコントローラ

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
Zend Framework入門連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、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編 」他、著書多数

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

WINGSプロジェクト 川北 季(カワキタ ミノル)

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

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング