HTTP リクエストに対する CakePHP の動作フロー
CakePHP を深く理解するために CakePHP が1回の HTTP リクエストに対して HTTP レスポンスを返るまでの動作フローを把握しておきます。
ここでは http://www.example.tld/ に CakePHP がインストールされているサーバへ http://www.example.tld/users/list/username/10 という HTTP リクエストを送った場合を解説します。
(1) HTTP リクエストを受ける
Web の枠組みで動作する以上 CakePHP も HTTP リクエストを受信しなければ動作できません。
CakePHP ではすべての HTTP リクエストをフロントコントローラである index.php が受信します。実際には http://www.example.tld/ と指定して http://www.example.tld/index.php が HTTP リクエストを受信できるように mod_rewrite が URL 書き換えます。
mod_rewrite とはパターンにあわせて URL を書き換えるための Apache の拡張モジュールです。
(2) URL からコントローラ名、アクション名、パラメータを解析する
フロントコントローラである index.php が HTTP リクエストを受けると、その URL をコントローラ名とアクション名とパラメータへ分離します。分離は CakePHP がインストールされている場所からスラッシュ区切りで「コントローラ名」「アクション名」「パラメータ」と順番に続いているものとして解釈します。
たとえば http://www.example.tld/users/list/username/10 の場合は http://www.example.tld/ に CakePHP をインストールしていますので、コントローラ名は http://www.example.tld/ の後ろの users 、アクション名は http://www.example.tld/users/ の後ろの list 、パラメータは http://www.example.tld/users/list/ の後ろの username/10 となります。しかし、パラメータはそこからさらにスラッシュで分離します。つまり username/10 の場合は username と 10 というふたつのパラメータになります。
http://www.example.tld/users/list/username/10
~~~~~ ~~~~ ~~~~~~~~ ~~
(1) (2) (3) (4)
(1) コントローラ名
(2) アクション名
(3) パラメータ1
(4) パラメータ2(3) URL で指定されたコントローラ名に対応するクラスをインスタンス化する
URL から解析したコントローラ名に対応するクラスをインスタンス化します。
今回の例ではコントローラ名は users でしたので、 CakePHP の /app/controllers ディレクトリから users_controller.php というファイルを見つけ出し、そこに書かれている UsersController クラスをインスタンス化します。
class UsersController extends AppController { // 前略… // このコントローラをインスタンス化します // 後略… }
(4) data[(ControllerName)][(FieldName)] をコントローラに取り込む
コントローラをインスタンス化したら次は HTTP パラメータの中から data[(ControllerName)][(FieldName)] という形式のデータがないか解析し、あった場合はコントローラが持つフィールド data に格納します。
今回の例では data[][] はありませんので、 CakePHP の基本的なデータ構造を参考にしてください。
class UsersController extends AppController { // 前略… // HTTP リクエスト中に data[][] 形式のデータがあった場合はこの配列へ格納します // アクション内からは $this->data でアクセス可能です var $data; // 後略… }
(5) 必要に応じてコンポーネントをインスタンス化する
コントローラは必要に応じてコンポーネントをインスタンス化します。
class UsersController extends AppController { // 前略… var $components = array("ACL", "Security"); // 後略… }
コンポーネントを参照してください。
(6) 必要に応じてモデルをインスタンス化する
コントローラがアクションの実行に必要なモデルをインスタンス化します。必須ではありませんがたいていのアクションはモデルを必要とします。
class UsersController extends AppController { // 前略… var $uses = array("User", "Subject"); // 後略… }
(7) URL で指定されたアクション名に対応するメソッドを実行する
data[][] の取り込みやコンポーネントのインスタンス化が終了したら URL から解析したアクション名に対応するメソッドを実行します。
今回の例では UsersController::list() を実行することになりますが、もし URL にパラメータがあった場合はその値を引数に取ります(次節を参照)。
(8) URL で指定されたパラメータを引数とする
もし URL にパラメータがある場合は、そのデータを引数としてアクションへ渡します。
今回の例では username と 10 というパラメータがありましたので UsersController::list(”username”, 10) を実行することになります。
class UsersController extends AppController { // 前略… function list($soft_column, $num) { // ここを実行します } // 後略… }
(9) 必要に応じてモデルを実行する
コントローラはアクションを実行する中であらかじめインスタンス化したモデルのメソッドを駆使して目的を達成します。
(10) 表示する画面に必要なデータをビューへ渡す
コントローラはアクションを実行する中で HTTP レスポンスとして返す HTML データの構築に必要なデータをビューへ渡します。
たとえば会員リストを出力したい場合は会員情報を要素とする配列をビューへ渡します。
class UsersController extends AppController { // 前略… function list($soft_column, $num) { $user_list = $this->User->findAll(); // データを取得して… $this->set("user_list", $user_list); // ビューへ渡す } // 後略… }
(11) URL で指定されたアクション名に対応するビューテンプレートをインスタンス化する
アクションが終了するとコントローラはビューをインスタンス化します。
(12) 必要に応じてヘルパーをインスタンス化する
コントローラが HTTP レスポンスとして返す HTML の構築に必要なヘルパーをインスタンス化します。たいていの場合 HtmlHelper と FormHelper が必要です。
class UsersController extends AppController { // 前略… var $helpers = array("Html", "Form"); // 後略… }
(13) コントローラのアクション内で渡された値をテンプレートへ差し込む
アクション内で渡されたデータを駆使して HTTP レスポンスとして返す HTML を構築します。
先の例では会員情報を要素とする配列を渡されましたので foreach 文で要素がなくなるまで繰り返し会員情報を出力します。
<html> <head> <title>会員リスト</title> </head> <body> foreach ($user_list as $user) : 名前:echo $user[name]; <br /> 愛称:echo $user[nickname]; <br /> 趣味:echo $user[hobby]; <br /> <hr /> endforeach </body> </html>
(14) HTTP レスポンスを返す
値をテンプレートへ差し込んだらそのデータをまるごと HTTP レスポンスとしてブラウザへ返します。
<html>
<head>
<title>会員リスト</title>
</head>
<body>
名前:太郎<br />
愛称:タロー<br />
趣味:ギター<br />
<hr />
名前:次郎<br />
愛称:ジロー<br />
趣味:読書<br />
<hr />
名前:三郎<br />
愛称:サブ<br />
趣味:テニス<br />
<hr />
</body>
</html>« 「より実践的な CakePHP の使い方」へ | トップへ | 上の階層へ | 「リリースへ向けてのコーディング」へ »
