目次


Agavi による MVC プログラミング入門

第 1 回 Agavi を使って、まったく新しい世界の扉を開く

Agavi フレームワークを使用してスケーラブルな Web アプリケーションを作成する方法を学ぶ

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: Agavi による MVC プログラミング入門

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:Agavi による MVC プログラミング入門

このシリーズの続きに乞うご期待。

はじめに

PHP について真面目に勉強してきた PHP 開発者であれば、Symfony や CakePHP、そして Zend Framework などの PHP アプリケーション開発フレームワークについては既にご存知のはずです (そしておそらく使ったこともあるはずです)。これらのフレームワークは、ほとんどのアプリケーション要件を満たす包括的な API を提供しているため、PHP アプリケーション開発の確固たる基盤となります。また、サード・パーティーのライブラリーやコミュニティーが開発するコンポーネントに追加機能として統合するのも簡単です。

上記に挙げたフレームワークが最もよく使用されていることに間違いはありませんが、他に選択の余地がないわけではありません。代わりの手段として選択できるフレームワークの数は毎月のように増えています。この連載では、そのようなフレームワークの 1 つである Agavi に焦点を当てます。柔軟でスケーラブルな Agavi は、プロの PHP 開発者であれば誰にとっても真剣に検討する価値のあるフレームワークです。

この連載では、Agavi を使用した MVC ベースのアプリケーション開発の基本をひと通り紹介し、フレームワークの基本概念と、Agavi ならではの独特な手法を利用して素早く効率的に本格的な Web アプリケーションを一から作成する方法を説明します。このプロセスを通して、このフレームワークの巧妙さと、これほどまでにセキュアで拡張性の高いフレームワークにしている設計決定を理解すれば、皆さんの PHP 開発ツールキットに Agavi はかけがえのないフレームワークとして加わることになるはずです。それでは、さっそく本題に入りましょう。

Agavi を選ぶ理由とは

まずは、Agavi とは何であり、何が Agavi を特別なものにしているのかという基本的な質問に答えるところから始めます。

Agavi の公式 Web サイトの説明によると、Agavi は「MVC パラダイムに基づいた、パワフルでスケーラブルな PHP5 アプリケーション・フレームワーク」であるとあります。Agavi は PHP ベースの Web アプリケーションを作成およびデプロイするための包括的なツールキットになるとともに、セキュリティー、データ・キャッシュ、国際化対応、入力検証、データベース抽象化などのサポートが組み込まれています。元々 Agavi は Mojavi プロジェクトから分岐して開始されましたが、現在はドイツを拠点とするソフトウェア会社である有限会社 Bitextender が維持管理し、GNU Lesser General Public License 2.1 の下でコミュニティーにリリースされています。

Agavi が興味深い理由はさまざまにありますが、私がその上位 3 位に挙げる理由は以下のとおりです。

  1. 第 1 に、コードの再利用性に重点を置く Agavi では、開発者がアプリケーションの機能に対して異なるインターフェースを容易に作成することができます。この点は、内部機能に対して HTML インターフェースと SOAP インターフェースの両方を公開しなければならないことの多い Web アプリケーションのコンテキストでは、特に重要な点です。例えば、アプリケーションの既存の検索エンジンの機能に対して SOAP インターフェースを作成したいとします。その場合、Agavi では新しい出力タイプを定義し、既存の機能の出力を新しいフォーマットで提供するレンダラーを定義すればよいだけの話です。既存の機能を微調整する必要はありません。このようにプロセス全体が透過的で、容易に実現できるようになっています。
  2. 第 2 に、Agavi は高度な URL ルーティング・メカニズムを提供し、アプリケーションの機能に URL ルートをマッピングする方法を大々的に構成できるようにしています。このルーティング・メカニズムは何よりも、オプション・パラメーターと必須パラメーター、デフォルト値、ネストされたルート、そしてコールバック関数をサポートします。これは Agavi の最も重要な機能の 1 つです。Agavi アプリケーション構成の他のすべての側面と同じく、このルーティング・メカニズムは一貫して XML で表現され、Agavi の構成サブシステムが、アプリケーションのグローバルな設定および変数に実行時にアクセスできるようにします。
  3. 第 3 に、Agavi にはそのまますぐに使える、極めて厳重なリクエスト・フィルタリング機能と入力検証機能が用意されています。フィルターは、コントローラー・メソッドの事前処理と事後処理に使用することができます。リクエストごとにリクエスト・パラメーターの妥当性が検証され、不明なパラメーターについては Agavi が自動的に取り除くため、SQL インジェクションなどの攻撃を受けるリスクが大幅に減ります。ストリング、数値、タイムスタンプ、E メール・アドレス、ファイルの検証といった共通タスクのための組み込みバリデーターが多数用意されている他、正規表現を使った検証を実行することも、組み込みバリデーターでは十分でないような場合にはカスタム・バリデーターを定義することも可能です。これらの機能すべてが、Web アプリケーション開発に関連するフレームワークのなかで、Agavi を最もセキュアなフレームワークの 1 つにしています。

上記の他、Agavi は以下の機能も提供します。

  • 条件付きキャッシング・エンジン
  • 最もよく使われているデータベース・システム (MySQL、PostgreSQL、SQL Server を含む) および ORM (Propel、Doctrine を含む) のサポート
  • セッション管理エンジン
  • カスタマイズ可能なテンプレート (OOP 原則に完全準拠)

全体的に見ると、かなり賢いフレームワークです。それでは、このフレームワークを実際に使い始めてみましょう。

Agavi のインストール

この連載では、Apache/PHP/MySQL 開発環境がセットアップされていること、PHP と XML の実用的な知識があること、PHP の単純なデータ型と複雑なデータ型の両方を扱い慣れていることを前提とします。また、一般的な OOP および SOAP の概念についての十分な知識と、PHP の DOM (Document Object Model) 拡張による XML ツリー生成についてある程度の知識を持っていることも必要です。この連載では、PHP V. 5.2.6 と Apache V. 2.2.11 を使用します。

まず始めに、以下のステップに従って Agavi アプリケーションに必要な基本ディレクトリー構造を作成してください。

ステップ 1: アプリケーションのディレクトリー構造を作成する

カレント・ディレクトリーを Web サーバーのドキュメント・ルート・ディレクトリー (通常、Linux® では /usr/local/apache/htdocs、Windows® では C:\Program Files\Apache\htdocs) に変更し、アプリケーション用の新しいサブディレクトリーを作成します。この後すぐに理由を説明しますが、このディレクトリーには wasp/ という名前を付けます。

shell> cd /usr/local/apache/htdocs
shell> mkdir wasp

この連載では一貫して、このディレクトリーを $WASP_ROOT として参照します。

このディレクトリー内に、lib/ という名前のもう 1 つのサブディレクトリーを作成します。

shell> cd wasp
shell> mkdir lib

ステップ 2: 仮想ホストの設定を定義する

アプリケーションにアクセスしやすくするため、新しい仮想ホストを定義し、その仮想ホストをアプリケーションの Web ルート・ディレクトリーに設定します。このステップはオプションですが、特に複数のアプリケーションを同時に実行している開発マシンで作業する場合には、このオプションを使用することを推奨します。こうすることによって、ターゲット・デプロイメント環境により近いレプリカが作成されるためです。

アプリケーションに対する仮想ホストを指定してセットアップするには、Apache 構成ファイル (httpd.conf または httpd-vhosts.conf) を開いて以下の行を追加します。

NameVirtualHost 127.0.0.1
<VirtualHost 127.0.0.1>
    DocumentRoot "/usr/local/apache/htdocs/wasp/pub"
    ServerName wasp.localhost
</VirtualHost>

上記の行によって、$WASP_ROOT/pub/ ディレクトリーに対応するドキュメント・ルートを持つ新しい仮想ホスト http://wasp.localhost/ が定義されます。Web サーバーを再起動して、この新しい設定を有効にしてください。注意する点として、この新規ホストを認識させるために、ネットワークのローカル DNS サーバーを更新しなければならない場合もあります。

ステップ 3: Phing をダウンロードしてインストールする

Agavi はアクション、ビュー、テンプレート、およびバリデーターのコードを自動的に生成するために Phing ビルド・システムを利用します。Phing には PHP 5.0 以降が必要です。Phing をインストールするのに最も簡単な方法は、インストール済みの PHP システムにデフォルトで含まれている自動 PEAR インストーラーを使うことです。

自動 PEAR インストーラーを使う場合、以下のコマンドをシェル・プロンプトで実行するだけで Phing をインストールすることができます。

shell> pear channel-discover pear.phing.info
shell> pear install phing/phing

このコマンドを実行すると、PEAR インストーラーが新しいチャネルに接続し、Phing パッケージをダウンロードしてシステムの適切な場所にインストールしてくれます。この記事では Phing V. 2.3.3 を使用します。

Phing パッケージを手動でインストールする場合は、PEAR のホーム・ページにアクセスしてソース・コード・アーカイブをダウンロードし、ファイルを目的の場所に解凍してください。パッケージのホーム・ページへのリンクは、この記事の「参考文献」に記載されています。ただし手動でインストールするには、PEAR のパッケージ編成構造についての知識があることが前提となります。

ステップ 4: Agavi をダウンロードしてインストールする

次のステップは、Agavi フレームワークをダウンロードしてアプリケーションに追加することです。この時点で、Agavi ライブラリーをアプリケーションとバンドルするか、あるいはユーザーが自分でダウンロードしてインストールするという形をとるかについても決めなければなりません。どちらの方法にも以下の利点と欠点があります。

  • ユーザーが自分で Agavi ライブラリーをダウンロードしなければならないようにすれば、ユーザーは常に、最新のビルド (最新のバグ・フィックスが追加されたビルド) にアクセスすることになります。ただし、これは初心者のユーザーにとっては手強いプロセスとなり得ます。さらに、新しいライブラリーにアプリケーションの開発時に使用したバージョンとの後方互換性がない場合には、追跡が困難な異常なバグが発生する可能性もあります。
  • Agavi ライブラリーをアプリケーションにバンドルすると、上述のようなバージョンの互換性の問題が発生しないので、ユーザーは確実にアプリケーションをすぐに使用し始めることができます。その一方、ユーザーを Agavi の特定のバージョンに固定させることになるため、新しい機能や必要なバグ・フィックスが追加された新しいバージョンへのアップグレードが難しくなるかもしれません。

この連載では、Agavi ライブラリーはアプリケーションにバンドルされるという前提にします。この前提に従い、Agavi の公式 Web サイトから最新バージョンの Agavi フレームワーク (この連載では Agavi V 1.0.1 を使用) をダウンロードして一時的な場所に解凍し、抽出された src/ ディレクトリーを以下のように $WASP_ROOT/libs/agavi にコピーします。

shell> cp -R /tmp/1.0.1/src /usr/local/apache/htdocs/wasp/libs/agavi

抽出された bin/ ディレクトリー内にある agavi-dist (Linux) ファイルまたは agavi.bat-dist (Windows) ファイルの名前を変更して、それぞれ $WASP_ROOT/agavi (Linux)、$WASP_ROOT/agavi.bat (Windows) にコピーします。このファイルが、Agavi フレームワークで共通のさまざまなコード作成タスクを自動化する Agavi ビルド・スクリプトです。

shell> cp /tmp/agavi-1.0.1/bin/agavi-dist /usr/local/apache/htdocs/wasp/agavi
shell> chmod +x /usr/local/apache/htdocs/wasp/agavi

ステップ 5: Agavi ビルド・スクリプトを構成してテストする

最後のステップは、Agavi ビルド・スクリプトを構成し、このスクリプトにシステム上での Agavi ファイルの場所を指示することです。スクリプトをテキスト・エディターで開き、$AGAVI_SOURCE_DIRECTORY 変数を $WASP_ROOT/libs/agavi のパス (絶対パスが理想ですが、相対パスでも機能します) で更新します。以下は、Linux での更新例です。

SET AGAVI_SOURCE_DIRECTORY="./libs/agavi"

Windows の場合には、PHP バイナリーへの完全なディスク・パスを定義する PHP_EXECUTABLE 変数も設定する必要があります。以下はその一例です。

SET AGAVI_SOURCE_DIRECTORY="./libs/agavi"
SET PHP_EXECUTABLE="C:\Program Files\PHP\php.exe"

ファイルを保存した後、カレント・ディレクトリーを $WASP_ROOT に変更し、以下のコマンドを実行してファイルをテストします。

shell> agavi status
図 1. agavi status コマンドの出力
agavi status コマンドの出力
agavi status コマンドの出力

図 1 は、Linux での出力例です。この出力には、PHP、Phing、Agavi、そして既存のプロジェクトのバージョンとディレクトリー・パスが含まれています。お使いのシステムで同じような出力が表示されない場合は、何らかの問題があるので、トラブルシューティングを行ってください。トラブルシューティング・プロセスの参考になる Agavi マニュアルの該当セクションへのリンクが、「参考文献」に記載されています。一方、上記と同じような出力が表示された場合には、Agavi アプリケーションの基盤が用意されたことになるので、コードの追加に取り掛かれます。

新規 Agavi プロジェクトの開始

実際の作業に取り掛かる前に、これから作成するサンプル・アプリケーションについて理解しておくことが肝心です。このサンプル・アプリケーションは架空の自動車販売店の Web サイト上のアプリケーションであり、この販売店では中古のスポーツカーの販売を専門としています。当初、販売店の Web サイトにはごくありきたりなものが計画されていました。それは、基本的な連絡先とサービス情報、そしてサイトの訪問者が販売担当者と直接連絡を取るための問い合わせフォームを表示する静的ページで Web サイトを構成するというものでした。ところが、販売店チームは遅めの昼食の席で面白い考えを思いつきました。それは、オンライン中古車広告システムです。このシステムでは、販売員が中古のフェラーリとランボルギーニの写真と説明をアップロードし、買い手が予算、メーカー、キーワードを基準にして中古車のリストを検索できるようにします。サイトの管理人はアップロードされた中古車のリストに直接アクセスし、検索結果に表示する上で適切と思われる中古車を手動で承認します。また、中古車のリストのデータベースには、他のアプリケーションと統合しやすいように SOAP インターフェースでアクセスできるようにします。

チームはこのシステムにぴったりの名前まで考案しました。それは Web Automobiles Sales Platform、略して WASP です。

WASP サンプル・アプリケーションは、日常のアプリケーション開発で遭遇する一般的な要件を満たすように考えられています。具体的には、静的なページ、入力フォーム、写真のアップロード、ログインで保護された管理パネル、データのページングとソート、複数の出力タイプ、キーワード検索です。これらの機能を実装するには、フォーム処理、入力検証、セッション管理、認証とセキュリティー、CRUD データベース操作、Web サービス API、そしてサード・パーティー・ライブラリーの統合についての詳細を理解する必要があります。そうすることが、Agavi でのアプリケーション開発を理解する上で適切な出発点となります。

このアプリケーションの作成に取り掛かるには、まず Agavi ビルド・スクリプトを使って新しいプロジェクトを初期化します。カレント・ディレクトリーを $WASP_ROOT に変更して、以下のコマンドを実行してください。

shell> agavi project-wizard

以下のように、プロジェクトに名前を設定します。

Project name [New Agavi Project]: WASP
Project prefix (used, for example, in the project base action) [Wasp]: WASP

それ以降に出されるプロンプトに対してはデフォルト値を受け入れますが、以下のプロンプトだけは例外です。

Should an Apache .htaccess file with rewrite rules be generated (y/n) [n]? y

これにより、プロジェクト・ウィザードが自動的に空のアプリケーション・コンテナーを作成し、そのコンテナーにデフォルト設定を入力します。図 2 は、ウィザードの動作を示すスクリーン・キャプチャーです。

図 2. Agavi プロジェクト・ウィザードの動作
Agavi プロジェクト・ウィザードの動作
Agavi プロジェクト・ウィザードの動作

このプロセスの一環として、プロジェクト・ウィザードはいくつかの新しいディレクトリーをアプリケーション階層に追加します。追加されるディレクトリーとは、アプリケーション・コードを保存するための $WASP_ROOT/app/、画像やスタイルシート、そして静的な HTML ページなどの Web でアクセス可能なコンテンツを保存するための $WASP_ROOT/pub/、そして開発ファイルを保存するための $WASP_ROOT/dev/ です。

最終的には、図 3 のような結果になります。

図 3. Agavi アプリケーションのファイル・レイアウト
Agavi アプリケーションのファイル・レイアウト
Agavi アプリケーションのファイル・レイアウト

$WASP_ROOT/dev/ には Apache の .htaccess ファイルのコピーが含まれていることに注意してください。これは SVN や CVS などの分散バージョン管理システムを使用するプロジェクト専用のコピーです。このディレクトリーにファイルのコピーを置くことによって、共有ワークスペースに作業ファイルのコピーを作成することなく、作業中のファイルのコピーを保持することができるわけですが、このサンプル・アプリケーションの場合には、このディレクトリーを削除しても問題ありません。このディレクトリーの有用性についての詳細は、「参考文献」に記載されている Agavi マニュアル・ページへのリンクにアクセスしてください。

プロジェクトの作成プロセスが完了したら、Web ブラウザーを開いて、前のステップでセットアップした仮想ホストにアクセスしてください。URL として http://wasp.localhost/ と入力すると、図 4 の Agavi ウェルカム・ページが表示されます。

図 4. 新規 Agavi アプリケーションのウェルカム・ページ
新規 Agavi アプリケーションのウェルカム・ページ
新規 Agavi アプリケーションのウェルカム・ページ

おめでとうございます!これで、(極めて単純とは言え) 実際に使える Agavi アプリケーションを立ち上げることができたので、今度はアプリケーションの内部を詳しく見て行きます。その後、前述の機能をサポートするようにアプリケーションを変更する作業に入ります。

基本概念について

Agavi でのアプリケーション開発は、従来からのモデル・ビュー・コントローラー・パターンに従います。つまり、データ・モデルを処理ロジックから切り離し、処理ロジックをユーザーが目にする出力とは切り離すというパターンです。Agavi はこのパターンを実装する手段として、モデル、アクション、ビュー、ルートを使用します。

  • モデルはデータを表し、通常は (必ずではないにしろ) データベースに保存されたデータの管理、操作、および計算の実行に必要な関数を提供します。Agavi には最もよく使われているデータベースのアダプター、そして Propel および Doctrine ORM のそれぞれに対応するドライバーが組み込まれています。
  • ビューはユーザーが目にする出力を表します。ビューが密接に結合されるページ・テンプレートには、ビューをユーザーに正しく表示するために必要なレイアウト・コードまたはマークアップが含まれています。ビューではテンプレートの変数に値を割り当てることもできます。割り当てられた値は、実行時に自動的にページ・テンプレートに取り込まれます。
  • アクションはモデルとビューとを結ぶリンクを提供します。アクションはモデルを使用してアプリケーション・データを変更し、ビューを呼び出して変更結果をユーザーに表示します。アクションは複数のビューを持つことができます。そのため、複数のビューのなかから、任意の時点で表示される結果に応じて異なるビューを呼び出すことができます。
  • ルートはユーザー・リクエストとアクションとを結ぶリンクを提供します。ユーザーがアプリケーションの URL に対してリクエストを送信すると、ルーティング・システムがそのリクエストをインターセプトします。そして URL のパターンを基準に、リクエストに対応するために呼び出すアクションを決定します。ルートはパターン・マッチングに正規表現を利用し、XML を使用して表現されます。

上記の説明でもまだ、この 4 つのコンポーネントがどのように組み合わせられるのか混乱していますか?Agavi アプリケーションでの Web リクエストの典型的なフローを最もわかりやすく説明しているのは、おそらく Agavi マニュアル自体に記載されている説明です (「参考文献」にリンクを記載)。その説明によると、「Web リクエストが到着すると、ルーティング・メカニズムによって実行される初期アクションが選択されます。選択されたアクションはモデルを呼び出し、アプリケーションの状態を必要に応じて変更します。アクションはまた、そのアクションが完了した後に実行するビューも選択します。そしてアクション完了後に、選択されたビューがアプリケーションの出力をレンダリングします」。

デフォルトでは、すべてのアクションは (当然のことですが) Default モジュール内にあります。しかし、Web アプリケーションの機能分野ごとにアクション (そして関連するモデルとビュー) をグループ化したいという場合も珍しくありません。このグループ化を実現する手段となるのが、モジュールです。例えばアプリケーションに検索、ユーザー・プロファイル管理、ニュースを対象としたサブシステムが組み込まれている場合、SearchProfilesNews という名前の別個のモジュールを作成し、それぞれのモジュールに対応するアクションを配置することができます。

この背景情報を踏まえて、プロジェクト・ウィザードによって生成されたコードで、デフォルトの Agavi ウェルカム・ページがどのように生成されているかを詳しく調べてみましょう。まず、$WASP_ROOT/app/config/routing.xml に保存されているアプリケーションのルーティング・テーブルの内容を見てください。リスト 1 を見ると、アプリケーションの index ページへのルートがあることがわかります。

リスト 1. アプリケーションの index ページへのルート
<?xml version="1.0" encoding="UTF-8"?>
<ae:configurations 
 xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" 
 xmlns="http://agavi.org/agavi/config/parts/routing/1.0">
  <ae:configuration>
    <routes>    
      <route pattern="" module="Welcome" action="Index" />
      ...
    </routes>
  </ae:configuration>
</ae:configurations>

ルート・エントリーには通常、patternmoduleaction の 3 つの属性が含まれています。pattern 属性はルートが突き合わせる URL パターンを指定し、module 属性と action 属性は、それぞれリクエストに対応するために呼び出すモジュール、アクションを指定します。デフォルトでは、Agavi は最初に見つかった一致の結果を使用します (そのため原則として、ルートは最も特殊なルートが先頭にきて、最も一般的なルートが最後のほうにくるように整理してください)。このデフォルトの振る舞いを変更するには、ルートに stop=false という属性を追加します。この設定は Agavi に対し、一致が見つかっても処理を続行するように指示します。

リスト 1 のルートは極めて一般的なルートです。このルートによって、Agavi はあらゆる URL リクエストに対し、Welcome モジュールの Index アクションを呼び出すことになります。このアクションは、Agavi プロジェクト・ウィザードが自動的に (PHP クラスとして) 作成して、$WASP_ROOT/app/modules/Welcome/actions/IndexAction.class.php に配置します。

リスト 2. Index アクション
<?php
class Welcome_IndexAction extends WASPWelcomeBaseAction
{
  public function getDefaultViewName()
  {
    return 'Success';
  }
}
?>

すべてのアクション・クラスには、いくつかの標準メソッドを定義することができます。すると、Agavi はこれらのメソッドを使用して、リクエストのタイプごとに処理方法を決定します。例えば、executeRead() メソッドは GET リクエストの処理方法を指定する一方、executeWrite() メソッドは POST リクエストの処理方法を指定します。この 2 つのメソッドをどちらも定義しない場合、すべてのアクションには最低でも、そのアクションのデフォルト・ビューを指定する getDefaultViewName() メソッドが必要です。リスト 2 のコードから、IndexAction のデフォルト・ビューは Success という名前であることがわかります。

Agavi のファイル命名規則によると、Welcome モジュールに含まれる Index アクションの Success ビューが保存されている場所は、$WASP_ROOT/app/modules/Welcome/views/IndexSuccessView.class.php です。このファイルを見つけて開くと、リスト 3 のような内容になっています。

リスト 3. Success ビュー
<?php
class Welcome_IndexSuccessView extends WASPWelcomeBaseView
{
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    $this->setupHtml($rd, 'simple');   
    $this->setAttribute('agavi_release', AgaviConfig::get('agavi.release'));
  }
}
?>

ビューをレンダリングする際に、Agavi は自動的に executeXXX() というメソッドを呼び出します。ここで、XXX は必要な出力タイプです。したがって、HTML 出力を生成するには、ビューに executeHtml() メソッドが含まれていなければなりません。このメソッドが必要なテンプレート変数を設定し、レンダリング用のテンプレートを準備します。この少し後で説明しますが、ビューは HTML 以外のフォーマットで出力を生成することもできます。例えば、XML 出力を生成するには executeXml() メソッドを定義し、YAML 出力を生成するには executeYaml() メソッドを定義するといった具合です。ビューに含まれるテンプレート変数を定義するには、まず setAttribute() メソッドを呼び出し、それからテンプレートそのもののなかで $t 配列のキーとして変数にアクセスします。

ここで指摘しておく価値がある点は、ビューによって生成される HTML マークアップはビュー・クラス・ファイルには保存されず、別のテンプレート・ファイルに保存されることです。Agavi の命名規則に従い、このテンプレート・ファイルにはビューにちなんだ名前が付けられます。したがって、IndexSuccessView のテンプレートは $WASP_ROOT/app/modules/Welcome/templates/IndexSuccess.class.php に配置されます。このファイルを開くと、図 4 の出力を生成した HTML マークアップを確認することができます。

リスト 4. HTML マークアップ
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" 
 lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <base href="<?php echo $ro->getBaseHref(); ?>" />
    <title>Welcome to Agavi!</title>
  </head>
  <body>
    <div>
      <p>You are running <em><?php echo $t['agavi_release']; ?>
       </em></p>
    </div>
  </body>
</html>

リスト 3 に記載したコード・スニペットでは、ビュー内で setAttribute() メソッドを使ってテンプレート変数 $t['agavi_release'] を定義した上で、テンプレート・ファイル自体に動的に取り込まれるようにする方法に注目してください。

最後に注意する点として、ビューが Web にアクセスして使用するファイル・アセット (画像ファイル、JavaScript ライブラリー、Flash 動画など) は、アプリケーションの公開エリア (この例での場合は $WASP_ROOT/pub/) に保存し、テンプレート内から適切に参照してください。

これまでの説明を簡単にまとめると、任意のアプリケーション URL に対する HTTP GET リクエストは Agavi のルーティング・サブシステムによって自動的に Welcome/IndexAction と一致することになります。このアクションは、getDefaultViewName() メソッドによって、呼び出す対象のビューが IndexSuccessView であることを認識します。続いて IndexSuccessView はその executeHtml() メソッドを呼び出して HTML 出力を生成し、いくつかのテンプレート変数を HTML マークアップに取り込んでから、出力をクライアントに送信して表示できるようにします。

この説明からすぐに、以下の 3 つのことがわかるはずです。

  1. 第 1 に、アクションとビューに適切な名前を付けて、適切に配置しさえすれば、他に必要となる作業はほとんどありません。後はフレームワークが自動的にファイルを見つけて実行してくれるので、手動による介入は必要ありません。さらに、ファイル命名規則が多少理解しにくいと思ったとしても、安心してください。この後、「静的コンテンツの提供」を読むとわかるように、細かい設定はすべてウィザードが引き受けてくれます。
  2. 第 2 に、URL リクエストを突き合わせ、リクエストを適切なアクションに転送する上では、ルートが重要な役割を果たします。これはまた、他のフレームワークとは違って、アクションは階層のどこにでも配置できることを意味します。そのため、アプリケーション URL が、異なるカテゴリーのアクションおよびモジュールが内部でどのように分類されているかを直接反映する必要はありません。同様に、セキュリティーと特権はモジュールではなく、アクションそのものに結び付けられます。
  3. 第 3 に、単一のアクションが複数のビューを使用することも、各ビューが異なる出力タイプを処理することも可能です。そのため、コードの再利用性は拡大され、アプリケーションの進化に合わせて、例えば後日、XML または RSS 出力用のビューを同じアクションに簡単に追加することができます。

アプリケーションの index ページとマスター・テンプレートの設定

Agavi の仕組みについての理解が多少深まったところで、いよいよアプリケーションの作成に取り掛かります。デフォルトの Agavi ウェルカム・ページは見た目がよいとは言え、必ずしも真っ先にユーザーに表示したいページであるとは限りません。そこで最初のステップとして、アプリケーションに新しい index ページを作成します。

まず、カレント・ディレクトリーを $WASP_ROOT に変更して、以下のようにプロジェクト・ウィザードによって自動的に生成された Welcome モジュールを削除します。

shell> rm -rf app/modules/Welcome
shell> rm -rf app/pub/welcome

続いて $WASP_ROOT/app/config/routing.xml にあるルーティング・テーブルを編集し、テーブルに含まれる各種エントリーを削除します。最終的にはリスト 5 のように (とりあえず) 空の構成になります。

リスト 5. ルーティング・テーブル
<?xml version="1.0" encoding="UTF-8"?>
<ae:configurations 
 xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" 
 xmlns="http://agavi.org/agavi/config/parts/routing/1.0">
  <ae:configuration>
    <routes>

    </routes>
  </ae:configuration>
</ae:configurations>

プロジェクト・ウィザードによって作成済みのデフォルト・モジュールには IndexAction と IndexSuccessView が含まれているので、アプリケーションの index ページとしてはこのモジュールが適切です。$WASP_ROOT/app/modules/Default/actions/IndexAction.class.php ファイルを任意のテキスト・エディターで開き、リスト 6 のコードが含まれていることを確認します。

リスト 6. Default/Index アクションの定義
<?php
class Default_IndexAction extends WASPDefaultBaseAction
{
  public function getDefaultViewName()
  {
    return 'Success';
  }
}
?>

次に、ビュー・ファイル $WASP_ROOT/app/modules/Default/views/IndexSuccessView.class.php が存在し、リスト 7 のコードが含まれていることを確認します。

リスト 7. Default/IndexSuccess ビューの定義
<?php
class Default_IndexSuccessView extends WASPDefaultBaseView
{
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    $this->setupHtml($rd);
    $this->setAttribute('_title', 'Index');
  }
}
?>

今度はアプリケーションの index ページのテンプレートを作成するため、テンプレート・ファイル $WASP_ROOT/app/modules/Default/templates/IndexSuccess.php を変更してリスト 8 のコードを含めます。

リスト 8. Default/IndexSuccess テンプレート
Welcome to WASP, your one-stop shop for used sports cars online. 
<p/>
We have a wide selection of used automobiles for your driving pleasure, 
 and all our models are backed with our unique 120-day money-back guarantee.  
<p/>
Use the links above to navigate this web site.

最後に、ルーティング・テーブルにエントリーを追加し、Agavi が index ページに対するすべてのリクエストを Default/IndexAction に転送するようにします (リスト 9 を参照)。

リスト 9. Default/Index ルートの定義
<?xml version="1.0" encoding="UTF-8"?>
<ae:configurations 
 xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" 
 xmlns="http://agavi.org/agavi/config/parts/routing/1.0">
  <ae:configuration>
    <routes>
      <!-- default action for site root "/" -->
      <route name="index" pattern="^/$" module="Default" action="Index" />
    </routes>
  </ae:configuration>
</ae:configurations>

ここでもう一度、Web ブラウザーで http://wasp.localhost/ にあるアプリケーションの index ページにアクセスしてみてください。図 5 に示す改良後の index ページが表示されるはずです。

図 5. WASP index ページ
WASP index ページ
WASP index ページ

もちろん、このままでは目を引くページとは言えません。イメージ・チェンジが必要なことは明らかです。

ページのレイアウト全体を変更するには 2 つの方法があります。1 つの方法は、当然、選択したページ・テンプレートにレイアウト・マークアップを追加することです。けれどもこの方法では、アプリケーションのページ・テンプレートごとに追加作業を繰り返さなくてはならないため、時間がかかるだけでなく、更新しやすいとも言えません。それよりも望ましいソリューションは、$WASP_ROOT/app/templates/Master.php に置かれたアプリケーションのマスター・テンプレートを変更して、すべてのページ・テンプレートに新しいレイアウトを自動的に反映させることです。

リスト 10 に、改良後のマスター・テンプレートのコードを記載します。

リスト 10. アプリケーションのマスター・テンプレート
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <base href="<?php echo $ro->getBaseHref(); ?>" />
    <link rel="stylesheet" type="text/css" href="/css/default.css" />
    <title><?php if(isset($t['_title'])) echo htmlspecialchars($t['_title']) 
     . ' - '; echo AgaviConfig::get('core.app_name'); ?></title>
  </head>
  <body>
    <!-- begin header -->
    <div id="header">
      <div id="logo">
        <img src="/images/logo.jpg" />
      </div>
      <div id="menu">
        <ul>
          <li><a href="#">Home</a></li>
          <li><a href="#">For Sale</a></li>
          <li><a href="#">Other Services</a></li>
          <li><a href="#">About Us</a></li>
          <li><a href="#">Contact Us</a></li>
        </ul>
      </div>
    </div>
    <!-- end header -->
    
    <!-- begin body -->
    <div id="body"> 
      <?php echo $inner; ?>
    </div>
    <!-- end body -->
    
    <!-- begin footer -->
    <div id="footer">
      <p>Powered by <a href="http://www.agavi.org/">Agavi</a>. 
      Licensed under <a href="http://www.creativecommons.org/">Creative Commons</a>.</p>
    </div>
    <!-- end footer -->
  </body>
</html>

上記のコードから、このマスター・テンプレートは 2 つの追加アセットを利用していることがわかります。1 つは CSS スタイルシート、そしてもう 1 つはロゴの画像です。この 2 つのファイルをアプリケーションの公開エリアに配置して、クライアントが HTTP で接続してファイルを取得できるようにしてください。それには、$WASP_ROOT/pub/ 内に css/ と images/ という 2 つのサブディレクトリーを作成し、必要なアセットをそれぞれのサブディレクトリーにコピーします (これらのアセットは、記事のダウンロード・アーカイブに含まれています)。

リスト 11 に説明のため、$WASP_ROOT/pub/css/default.css に記述されているスタイルシート・ルールを記載します。

リスト 11. アプリケーションのマスター・スタイルシート
body { 
  margin: 0; 
  padding: 0; 
  font-family: 'Verdana' sans-serif;
}

#header {
  height: 80px;
  background: #4062A8;
}

#logo {
  float: left;
  padding-left: 50px;
  padding-top: 5px;
}

#menu {
  float: right;
  background: #4062A8;
  margin-right: 20px;
}

#menu ul {
  list-style: none;
}

#menu li {
  margin-top: 35px;
  float: left;  
  padding-right: 25px;
  padding-left: 25px;
}

#menu a, #footer a {
  color: white;
  font-weight: bold;
}

#body {
  padding-top: 20px;
  padding-left: 50px;
  min-height: 375px;
}

#footer {
  font-size: x-small;
  color: white;
  float: right;
  text-align: right;
  background: #4062A8;
  width: 400px;
  clear: both;
  margin-top: 20px;
}

これでアプリケーションの index ページに再びアクセスすると、図 6 のようなページになっているはずです。

図 6. 改良後の WASP index ページ
改良後の WASP index ページ
改良後の WASP index ページ

この通り、ページの見栄えは前よりも断然良くなりました。

静的コンテンツの提供

これまで変更したのは、アプリケーションに含まれる既存のアクションだけですが、その一方、Agavi ビルド・スクリプトではアプリケーションに新しいアクションを追加するのもごく簡単です。これを説明するため、これから会社の「About Us」や「Services」ページなどの静的コンテンツを提供する StaticPageAction とそれに対応するビューを追加します。以下のステップは、新しい機能を Agavi アプリケーションに追加する際の標準プロセスを反映したものです。

ステップ 1: プレースホルダー・クラスを作成する

シェルに戻り、以下のように Agavi ビルド・スクリプトを呼び出します。

shell> agavi action-wizard

StaticContentAction という名前の新しいアクションをセットアップし、プロンプトが出されたら以下の値を入力して、この新規アクションを StaticContentErrorView と StaticContentSuccessView という2 つのビューに関連付けます。

Module name: Default
Action name: StaticContent
Space-separated list of views to create for StaticContent [Success]: Error Success

これで Agavi が自動的に必要なクラス・ファイルを生成して、適切な場所にファイルを配置するようになります。

ステップ 2: ルートを定義する

上記のプロセスが完了したら、$WASP_ROOT/app/routing.xml ファイルに戻り、新しく作成したアクションを参照する静的コンテンツへの新しい基本ルートを追加します (リスト 12 を参照)。

リスト 12. Default/StaticContent ルートの定義
<?xml version="1.0" encoding="UTF-8"?>
<ae:configurations 
 xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" 
 xmlns="http://agavi.org/agavi/config/parts/routing/1.0">
  <ae:configuration>
    <routes> 
       ...          
      <!-- action for static pages "/content/$page" -->
      <route name="content" pattern="^/content/(page:[\w-]+)$" module="Default" 
       action="StaticContent" />
 
    </routes>
  </ae:configuration>
</ae:configurations>

このルートは、これまで見てきたルートよりも多少複雑です。まず、name 属性が組み込まれていますが、この属性には、ルートを手動で生成する場合に使用可能なラベルを指定します (後ほど、その実際を説明します)。もう 1 つ複雑になっている点は、上記の正規表現は以下のどのフォーマットの URL とも一致することです。

/content/hello
/content/HelloWorld
/content/hello-world
/content/Hello-World-123

上記のすべての例では、明らかに最後のセグメントが変数なので、そのことを Agavi のルーティング・サブシステムに伝えなければなりません。そのための手段が、ルート定義の該当するセグメントを括弧で囲むことです。括弧を使用すると、Agavi マニュアルでキャプチャー・グループ (capture group) と呼ばれるものが作成されます。キャプチャー・グループは、URL の特定のセグメントを Agavi 変数に自動的に変換するために使用することができます。変換後の変数が最終的に検証されて AgaviRequestDataHolder オブジェクトに組み込まれ、アクションまたはビューからアクセスされることになります。

ステップ 3: 検証ルールを定義する

キャプチャー・グループを使用してルートを定義しても、パズルはまだ半分しか完成していません。ルートに含まれる変数がアクションまたはビューに辿り着くには、Agavi の極めて厳重な入力検証フィルターを通過する必要があります。デフォルトでは、このフィルターは最も厳しいレベルに設定されます。つまり、フィルターが認識しない (または特定の検証テストに合格しなかった) GET 変数や POST 変数は自動的に破棄され、アプリケーションまで辿り着くことは決してありません。この極めて厳しい入力サニタイズ・ポリシーが、Agavi アプリケーションをこれほどセキュアにしている理由の 1 つです。

Agavi に備わっている広範な組み込み入力バリデーターは、単純な XML ファイルによって構成することができます。入力バリデーターは、それが属するアクションの名前を共有し、モジュールの validate/ ディレクトリーに配置されます。したがって、StaticContentAction バリデーターの場合には、$WASP_ROOT/app/modules/Default/validate/StaticContent.xml にあるファイルを編集してリスト 13 の XML を入力します。

リスト 13. Default/StaticContent アクションの定義
<?xml version="1.0" encoding="UTF-8"?>
<ae:configurations
  xmlns="http://agavi.org/agavi/config/parts/validators/1.0"
  xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0"
  parent="%core.module_dir%/Default/config/validators.xml"
>
  <ae:configuration>
    
    <validators method="read">
      <validator class="regex">
        <arguments>
          <argument>page</argument>
        </arguments>
        <ae:parameters>
          <ae:parameter name="pattern">#^[\w-]+$#</ae:parameter>
          <ae:parameter name="match">true</ae:parameter>
        </ae:parameters>
      </validator>
    </validators>
        
  </ae:configuration>
</ae:configurations>

ごく単純なことで、上記の XML ブロックは page 変数に対して AgaviRegexValidator をセットアップし、バリデーター定義に指定された正規表現と一致するかどうかをチェックします。

ステップ 2 とステップ 3 の結果、URL /content/hello が渡されると、Agaviのルーティング・サブシステムと検証サブシステムが自動的にその URL をチェックし、page という名前の AgaviRequestDataHolder 変数を初期化して値 hello を割り当てるようになりました。

ステップ 4: アクションのコードを作成する

そもそも、URL のこの特定のセグメントをキャプチャーする理由は何なのでしょうか。これはもっともな疑問です。その答えは間もなく明らかになるので、それまではこのまま作業を進めて、$WASP_ROOT/app/modules/Default/actions/StaticContentAction.class.php にある StaticContentAction をセットアップします。リスト 14 のコードが含まれるように、このファイルを編集してください。

リスト 14. Default/StaticContent ビューの定義
<?php
class Default_StaticContentAction extends WASPDefaultBaseAction
{
  public function getDefaultViewName()
  {
    return 'Success';
  }
  
  public function executeRead(AgaviRequestDataHolder $rd)
  {
    return 'Success';
  }  
}
?>

前述したように、Agavi ではリクエストのタイプごとに、リクエストを処理するビューを明示的に指定しなければなりません。例えば、executeRead() メソッドは GET リクエストを処理する方法を指定する一方、executeWrite() は POST リクエストを処理する方法を指定します。StaticContentAction の場合、処理するのは GET リクエストだけなので、このアクションには executeRead() メソッドを含めるようにし、このメソッドが StaticContentSuccessView を参照するようにしなければなりません。

注意する点として、Success ビューが呼び出されるのは、前述の入力検証テストに合格した場合のみです。入力検証に失敗すると、Agavi のデフォルトの振る舞いによって Error ビューが生成されます。

ステップ 5: ビューのコードを作成する

ここからは、いよいよこのセクションの本題です。つまり、静的ページを提供する StaticContentSuccessView をセットアップします。$WASP_ROOT/app/modules/Default/views/StaticContentSuccessView.class.php にあるビュー・ファイルを開き、リスト 15 のコードを入力してください。

リスト 15. Default/StaticContentSuccess ビューの定義
<?php
class Default_StaticContentSuccessView extends WASPDefaultBaseView
{
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    $this->setupHtml($rd);
    $words = explode('-', $rd->getParameter('page'));
    array_walk($words, create_function('&$i', '$i = ucfirst(strtolower($i));'));
    $tmpl = 'StaticContent' . implode($words);
    if (file_exists(
     dirname($this->getLayer('content')->getResourceStreamIdentifier()) 
     . "/$tmpl.php")) {
      $this->getLayer('content')->setTemplate($tmpl); 
    } else {
      return $this->createForwardContainer(
       AgaviConfig::get('actions.error404_module'), 
       AgaviConfig::get('actions.error404_action'));      
    }
  }
}
?>

複雑なコードに見えるかもしれませんが、実際にはそうではありません。基本的に、このビューは URL リクエストを静的ページ・テンプレートに突き合わせ、テンプレートが存在する場合にはそのリクエストをレンダリングするというだけです。まずビューの executeHtml() メソッドが数ステップ前でルーティング・サブシステムによってセットアップされた page 変数を取得します。そのために使用するのは、 AgaviRequestDataHolder オブジェクトの getParameter() メソッドです。次に、取得した値を事前定義されたファイル命名規則に従ったフォーマットに設定しなおし、同じ名前を持つテンプレート・ファイルを検索してレンダリングを試みます。

例えば、クライアントがリクエストを /content/hello-world という URL に送信した場合、$rd->getParameter('page') の呼び出しによって hello-world という値が返されるため、ビューは $WASP_ROOT/StaticContentHelloWorld.php という名前のテンプレートを検索します。このテンプレート・ファイルが存在する場合、ビューはこのテンプレートをクライアントに渡します。このテンプレート・ファイルが存在しなければ、自動的にリクエストを Agavi のデフォルト Error404 ビューに転送するため、クライアントには「Page not found」エラーが表示されます。

この時点で、$WASP_ROOT/app/modules/Default/views/StaticContentErrorView.class.php にある StaticContentErrorView をセットアップし、入力検証に失敗した場合の振る舞いを指定するのも得策です (リスト 16 を参照)。

リスト 16. Default/StaticContentError ビューの定義
<?php
class Default_StaticContentErrorView extends WASPDefaultBaseView
{
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    return $this->createForwardContainer(
     AgaviConfig::get('actions.error404_module'), 
     AgaviConfig::get('actions.error404_action'));
  }
}
?>

この振る舞いは至って単純で、同じくデフォルト Error404 アクションにリクエストを転送するだけにすぎません。

この段階まで来たら、後は実際に静的ページを定義するだけです。図 6 (または、リスト 10 のテンプレート) をもう一度見てください。メイン・メニューには、静的コンテンツとして分類するのにふさわしい 2 つの項目、About Us と Other Services があります。そこで、$WASP_ROOT/app/modules/Default/templates/StaticContentAboutUs.php$WASP_ROOT/app/modules/Default/templates/StaticContentOtherServices.php のそれぞれで新しいテンプレート・ファイルを作成し、リスト 17 に示す静的コンテンツを入力します。

リスト 17. Default/StaticContentAboutUs テンプレート
We've been dealing with used sports cars since 1996, and have built up an 
 enviable reputation for honesty, transparency, and fairness in all our dealings. 
 Rest assured, when you buy a used car from us, you're not just buying an automobile...
 you're buying a solid guarantee of service and quality!
<p/>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 
 incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud 
 exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure 
 dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
 Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt 
 mollit anim id est laborum.
<p/>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 
 incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 
 nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 
 fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 
 culpa qui officia deserunt mollit anim id est laborum.

この作業が終わったら、Web ブラウザーを開いて http://wasp.localhost/content/about-us または http://wasp.localhost/content/other-services のどちらかにアクセスしてください。上記で定義した静的ページが表示されるはずです (図 7 を参照)。

図 7. 静的ページ
静的ページ
静的ページ

ステップ 6: すべてをリンクする

もう 1 つ、ちょっとした作業が残っています。それは、メイン・メニューの項目を新しく作成した静的コンテンツ・ページにリンクさせることです。それにはマスター・テンプレート・ファイルを開き、Agavi のルート・ジェネレーターを使用して、これらのページへのルートを自動的に生成します (リスト 18 を参照)。

リスト 18. 更新後のアプリケーションのマスター・テンプレート
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
...
      <div id="menu">
        <ul>
          <li><a href="<?php echo $ro->gen('index'); ?>">
           Home</a></li>
          <li><a href="#">For Sale</a></li>
          <li><a href="<?php echo $ro->gen('content', 
           array('page' => 'other-services')); ?>">Other Services</a>
           </li>
          <li><a href="<?php echo $ro->gen('content', 
           array('page' => 'about-us')); ?>">About Us</a></li>
          <li><a href="#">Contact Us</a></li>
        </ul>
      </div>
...
</html>

Agavi では、手動でルートを作成するのも簡単です。ビューまたはテンプレートのなかで、$ro によって表される AgaviRouting オブジェクトを使用し、ルートの名前 (ルートを定義したときにセットアップした name 属性を覚えていますか?) を設定してこのオブジェクトの gen() メソッドを呼び出すと、ルートが生成されます。ルート・パラメーターを配列内に指定すれば、gen() メソッドに 2 番目の引数として渡すことができます。

マスター・テンプレートの変更を保存して、アプリケーションの index ページに再びアクセスしてください。メイン・メニューの静的ページへのリンクがアクティブになっているはずです。

読者のなかでも厳格な方のために、Agavi アプリケーションでは実際にはもっと簡単な方法で静的ページを提供できることを指摘しておきます。それは、静的ページを HTML ファイルとしてアプリケーションの pub/ ディレクトリーに配置し、手動で静的ページにリンクするという方法です。ただし、これらのページは Agavi のマスター・テンプレートを使用できないため、独自のレイアウト・マークアップが必要になります。しかしこの場合、後になって更新が問題になるだけでなく、Agavi のキャッシングおよびセキュリティー・メカニズムのメリットが生かされません。

まとめ

かなりのボリュームでしたが、第 1 回目の記事の内容としては、こんなところです。今回は Agavi の紹介として、その独特の機能を説明すると同時に、このフレームワークを開発マシンにインストールして構成するプロセスを説明しました。また、Agavi による Web リクエストの基本的な処理方法、そして Agavi ビルド・スクリプトを使用して、新しいプロジェクトとクラス・ファイルのテンプレートを簡単にセットアップする方法も説明しました。そして最後に、WASP サンプル・アプリケーションでの作業に取り掛かりました。これは、この連載をとおしてテストベッド・アプリケーションの役割を果たすアプリケーションです。

今回取り組んだサンプル・アプリケーションはまだ初期の段階ですが、index ページや静的コンテンツを提供できるようにはなっており、さらに開発を進めるためのまともなマスター・テンプレートも用意されている状態です。このごく基本的な機能を実装するだけでも、Agavi アプリケーションの最も重要なコンポーネント (ルート、アクション、ビュー、バリデーター、テンプレート、モジュール) について理解することができ、連載の第 2 回目でより複雑な機能に対処するための基礎を固められるはずです。

この記事で説明した機能を備えた WASP アプリケーションのコード・アーカイブは、ダウンロードすることができます。ぜひ入手して、いろいろと試してみてください。実際に新しい機能を追加してみるのもよいかもしれません。何も壊れないことは保証するので、間違いなくいい勉強になるはずです。それでは次回まで、実験を楽しんでください!


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Open source, Web development
ArticleID=421083
ArticleTitle=Agavi による MVC プログラミング入門: 第 1 回 Agavi を使って、まったく新しい世界の扉を開く
publish-date=08252009