• [Zend Framework] Zend Frameworkのbootstrap.php

    Zend Frameworkを使ってMVCフレームワークで開発をしようとする場合、Zend Frameworkのリファレンスガイドではドキュメントルート直下に置いたindex.phpをフロントコントローラとして使います。そして本命のディスパッチ処理はもちろん、ビューやルータの設定、また必要であればログ(Zend_Log)や権限(Zend_Acl)の設定もこのファイルに書いてしまうことが多いと思います。 Zend Framework COMMUNUTY Wikiには、まだ作成途中ですがOfficial ZF QuickStartという項目があって、リファレンスガイドのやり方とはちょっと違っていたのでメモっておきます。 ディレクトリ構成は以下のようになっています。``` AppRoot/ application/ controllers/ views/ scripts/ library/ public/ ドキュメントルートはAppRoot/publicで、ここにindex.phpが配置されます。bootstrap.phpはAppRoot/applicationの直下に置きます。AppRoot/application以下はZend Frameworkのリファレンスガイドにも例があるのでおなじみかと思います。AppRoot/library以下には、Zend Frameworkのライブラリ含めた外部ライブラリを置くところになっています。 AppRoot/public/index.php は以下のようになっています。 < ?php require ‘../application/bootstrap.php’; bootstrap.phpをインクルードするだけです。 AppRoot/application/bootstrap.phpにこれまでindex.phpに記述していた内容を書けばOKです。内容はほんの一例です。 < ?php error_reporting(E_ALL | E_STRICT); // インクルードパスの追加 set_include_path('../library’ . PATH_SEPARATOR . get_include_path()); // autoloaderの設定 require_once “Zend/Loader.php”; Zend_Loader::registerAutoload(); // front controllerの設定 $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); $frontController->setControllerDirectory('../application/controllers’); $frontController->dispatch();
  • [Zend Framework] Zend_Controller_Action_Helper_ContextSwitchで独自のコンテクストを追加する方法

    Zend_Controller_Action_Helper_ContextSwitch(長い)で、独自のcontextを追加する方法を書きます。 デフォルトで組み込まれている機能(xmlとjson形式)の使い方は前のエントリーを参照ください。今回は自分の都合で、gif形式での方法を書きます。 新しいコンテキストを追加する方法は、addContext()を使います。 インターフェースは以下のようになっています。``` public function addContext($context, array $spec) $contextでコンテキスト名を指定し、$specでコンテキストの設定を配列で指定します。$contextがすでにあるコンテキストと重複した場合は、Zend\_Controller\_Action\_Exceptiongがスローされます。 $specには、配列のキーで設定名、値で設定値を指定します。設定名は、suffix、headers、callbacksがあります。ひとつづつ説明していきます。 **suffix** ViewRenderer に登録されているビュースクリプトのサフィックス(デフォルトでは .phtml)の前に追加するサフィックスです。ViewRendererを有効にしている場合、fooAction()のビュースクリプト名は、デフォルトでfoo.phtmlとなりますが、ContextSwitchアクションヘルパーでコンテキストスイッチを行うと、参照されるビュースクリプトはfoo.{suffix名}.phtmlとなります。 ‘suffix'=>'gif’ のように設定した場合は、foo.gif.phtmlというファイルがビュースクリプトとなります。 **headers** ヘッダの名前を配列のキー、値を配列の値とした値で、コンテキストスイッチを行ったときにレスポンスヘッダに追加したいヘッダを指定します。Content-Typeは必須だとおもうので、たとえば ‘headers'=>array(‘Content-Type'=>'image/gif’) という設定をします。個人的にはもう少し設定しますが今回は割愛します。 **callbacks** キーに'init'や'post'を含む配列で、それぞれコンテキストの初期化や後処理の際に使用するコールバック関数を指定します。たとえば、 ‘callbacks’ => array( ‘init’ => ‘initGifContext’, ‘post’ => ‘postGifContext’ ) のように設定してある場合、initGifContext()がinitContext()コール時に、コントローラのpostDispatch()時にそれぞれ実行されます。 デフォルトで組み込まれているjsonでは、 ‘callbacks’ => array( ‘init’ => ‘initJsonContext’, ‘post’ => ‘postJsonContext’ ) 1. $callbackが文字列なら、同名のクラスメソッドを探す 2. $callbackが文字列なら、PHP関数を探す 3. $callbackが配列なら、call\_user\_func()に引数として渡す 4. ここまでで関数が見つからなければZend\_Controller\_Action\_Exceptionをスローする これまでの説明を踏まえて、設定の例を以下に示します。``` $spec = array( 'suffix' => 'gif', 'headers' => array( 'Content-Type' => 'image/gif', ), 'callbacks' => array( 'init' => 'initGifContext', 'post' => 'postGifContext' ) ); $this->addContext('gif', $spec); ```あとは、コールバック関数のinitGifContext()とpostGifContext()の定義です。 jsonのものを参考に、それぞれ定義してみました。 **・initGifContext() - ビューレンダラーの解除**``` public function initGifContext() { $viewRenderer = Zend\_Controller\_Action\_HelperBroker::getStaticHelper('viewRenderer'); $view = $viewRenderer->view; if ($view instanceof Zend\_View\_Interface) { $viewRenderer->setNoRender(true); } } ```**・postGifContext() - gifファイルの出力**``` public function postGifContext() { $viewRenderer = Zend\_Controller\_Action\_HelperBroker::getStaticHelper('viewRenderer'); $view = $viewRenderer->view; if ($view instanceof Zend\_View\_Interface) { $vars = $view->getVars(); if (@readfile($vars\['file'\]) === FALSE) { throw new Exception('failed readfile()'); } } } ```アクションメソッドにて、ビューファイルにfileという名前で設定(assign())したgifファイルを出力する仕様になっています。 今回は新しいコンテクストの作り方として、Zend\_Controller\_Action\_Helper\_ContextSwitchを継承したクラスに書くことにします。 **MyGifContext.
  • [Zend Framework] Zend_ControllerアクションヘルパーのContextSwitch

    Zend Framework1.5から新しく追加されたContextSwitchアクションヘルパーを使ってみました。 あるページのレスポンス形式をhtmlに加えてrssやatomフィードも追加したいとか、Ajaxで受け取るデータをxmlとjsonの両方に対応したい場合に、新しくactionメソッドを追加したり、処理を複雑にしないで対応することができます。 例として、FooControllerのbarActionメソッドはある画面から非同期通信で呼び出されjson形式でデータを返していたが、あるパラメータが設定されていた場合にXML形式でレスポンスを返すように処理を追加するという処理を考えます。 おそらく私は今までならば以下のように処理をしていたと思います。``` public function barAction() { $format = $this->getRequest() ->getQuery(‘format’, “json”); if($format == "xml") { /\* XML形式で返す \*/ // レスポンスヘッダーの設定 $this->getResponse() ->setHeader('Content-Type', 'application/json'); } else { /\* JSON形式で返す \*/ // レスポンスヘッダの設定 $this->getResponse() ->setHeader('Content-Type', 'text/xml'); } // データの取得など ... // データの設定 $this->view->assign($data); // ビューレンダラーのOFF $this->getFrontController() ->setParam('noViewRenderer', true); // データの出力 $this->view->setScriptPath("path/to/view/"); echo $this->view->render($format . '.phtml'); } * レスポンスヘッダの設定 * ビューの設定 * (Onになっている場合は)ビューレンダラーのOff * ビューファイルのパスと、ファイルの設定 という処理を付け加える必要がありました。 ContextSwitchアクションヘルパーを使うことで、ここの処理が自動化されます。 では、ContextSwitchアクションヘルパーの設定をしてみます。ますinit()メソッドで以下のようにアクションヘルパーの初期化をします。``` public function init() { $contextSwitch = $this->\_helper->getHelper('contextSwitch'); $contextSwitch->addActionContext('bar', 'xml') ->addActionContext('bar', 'json') ->initContext(); } ```まずContextSwitchアクションヘルパーのオブジェクトを取得して、addActionContext()でコンテキストの設定を行います。barAction()メソッドに対してxmlとjsonのコンテキストを追加しています。 initContext()で初期化を行って、設定は終わりです。 アクションメソッドではデータの取得など特に処理を変更する必要はありません。 出力する値をアサインしておきます。``` public function barAction() { $this->view->bar = "bar"; } ```続いてビュースクリプトの設定を行います。 通常デフォルトであれば、ビュースクリプトのファイル名はbar.
  • [Zend Framework] Zend_Controllerでの基本的なフロントコントローラ

    Zend_Controllerでフロントコントローラ(Zend_Controller_Front)は以下のような役割を果たします。 リクエストを適切なActionControllerへ引き渡す レスポンスの内容を取得して、リクエスト元へ返す Zend_Controllerでの基本的なフロントコントローラの作り方について書きます。 ○インスタンスの生成 Zend_Controller_Frontはシングルトンパターンも実装しているので、常に1つのインスタンスしか生成できません。つまり、newはできません(コンストラクタはprivateになっています)。またオブジェクトのハードコピーも出来ません(__clone()もprivateになってます)。 インスタンスの生成にはstaticメソッドのgetInstance()を使用します。``` /* インスタンス生成 */ // できる例 $front = Zend_Controller_Front::getInstance(); // できない例// $front = new Zend_Controller_Front; /* オブジェクトのコピー */ // できる例 $copy = $front; // 参照先(オブジェクトのあるアドレス)をコピー // できない例 $copy = clone $front; // ハードコピー(オブジェクトそのものがコピーされる) **○コントローラディレクトリの設定** フロントコントローラを動作させるためには、コントローラのあるディレクトリへのパスを最低ひとつ設定しないといけません。設定にはsetControllerDirectory()またはaddControllerDirectory()を使用します。 // デフォルト(default)モジュールのコントローラディレクトリを設定 $front->addControllerDirectory(‘path/to/the/controller’); // もしくは $front->setControllerDirectory(‘path/to/the/controller’); // ‘blog'モジュールのコントローラディレクトリを設定 $front->addControllerDirectory(‘path/to/controller’, ‘blog’); // もしくは $front->setControllerDirectory(‘path/to/controller’, ‘blog’); // 複数のモジュールを設定 $front->setControllerDirectory(array( ‘default’ => ‘path/to/controller’, ‘blog’ => ‘path/to/blog-module/controller’ )); // こんなのも可能です $front->addControllerDirectory(‘path/to/controller’) ->addControllerDirectory(‘path/to/blog-module/controller’, ‘blog’);
  • [Zend Framework] Zend_Controller クイックスタート

    復習の意味も込めて、Zend_Controllerについて。 Zend Frameworkのリファレンスガイドとソースコードを参考に書いていきます。 Zend_ControllerはZendFrameworkでのMVCモデルの根幹をなす部分で、フロントコントローラパターンを実装しています。 フロントコントローラパターンでは、リクエストをいったんフロントコントローラであるZend_Controller_Frontで受け取り、URLにもとづいて対応するアクションコントローラー(Zend_Controller_Actionを継承したクラス)のアクション(コントローラ内のメソッド)に処理を割りあてます。 アクションコントローラーはXxxController.php(最初の文字は大文字です)というファイルに、XxxControllerという名前で、Zend_Controller_Actionを継承したクラスを定義したものです。 アクションはアクションコントローラー内にyyyActionという名前で定義されているpublic メソッドです。``` // XxxController.phpの内容 require_once ‘Zend/Controller/Action.php’; class XxxController extends Zend_Controller_Action { public function yyyAction() { } } たとえば以下のようなURLにリクエストがあったとします。 http://exapmle.com/foo/bar この場合は、まずフロントコントローラで処理を受け取り、FooConroller.php内のFooControllerというクラスの、barAction()というメソッドが実行されます。ちなみに、コントローラー名が省略された場合にはindexコントローラーであるとみなされ、アクション名が省略された場合は同様にindexアクションであるとみなされます。 以下で、Hello Worldを出力するシンプルなアプリケーションの作成例を書きます。 今回は以下のようにアプリケーションを配置すると仮定し、http://localhost/ にアクセスした場合の例を書きます。 htdocs/ ├ application/ │ ├ controllers/ │ ├ models/ │ └ views/ │ ├ index.php └ .htaccess すべてのリクエストは一度フロントコントローラで受け取ります。今回この役割を果たすのは、htdocs直下にあるindex.phpです。 このPHPファイルにリクエストをまとめるために、apacheのmod\_rewriteを用いてURLを書き換えます。もし、apacheのmod\_rewriteが有効になっていない場合は有効にしておいてください。設定が有効になっていることを確認したら、.htaccessに以下のような記述を追加します。 RewriteEngine on RewriteRule !.(js|ico|gif|jpg|jpeg|png|css)$ index.php これは画像やスタイルシートへのリクエスト以外を、フロントコントローラ(htdocs/index.php)へ向けるための設定です。ここで設定した拡張子以外でもフロントコントローラへ処理をまわしたくないものがあれば、その拡張子を追加してください。 続いて、フロントコントローラの役割を果たすindex.phpの内容を以下のように書きます。 require_once ‘Zend/Controller/Front.php’; Zend_Controller_Front::run(‘application/controllers’); Zend\_Controller\_Front::run()の引数部分には、コントローラのあるディレクトリまでのパスを書きます。 これでリクエストされたurlに対応したコントローラのアクションへ処理が渡されます。 今回は、http://localhost/にアクセスする例ですが、このURLはコントローラー名とアクション名が省略されています。 上でも述べましたが、コントローラ名とアクション名が省略された場合は、それぞれindexという名前のものが割り当てられます。 今回の場合は、htdocs/application/controllers/IndexController.php のファイルに定義されている、IndexControllerクラスのindexAction() という関数が実行されます。 続いてコントローラを作成します。 htdocs/application/controllers ディレクトリ以下にIndexController.phpというファイルを作って、以下のように書きます。 require_once ‘Zend/Controller/Action.