CodeZine(コードジン)

特集ページ一覧

CakePHP内の処理を理解する

PHPフレームワークの処理の流れを追う

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/12/18 00:00

目次

1.htaccess(mod_rewrite)の技法

 CakePHPでは、

http://cakeのパス/コントローラ/メソッド/パラメータ

 というURLで実行すると、以下の「モデル」「コントローラ」「ビュー」クラスが自動的に読み込まれ、セキュリティに必要な処理が行われます。またデータベースへのアクセスやビジネスロジックの実行、テンプレートを使用した表示などの作業が自動的に行われていきます。

リクエストで読み込まれるクラス
クラス説明
モデルデータベーステーブルへのアクセスクラス
コントローラURLで指定されたコントローラ(メソッドの内容が記述されている)クラス
ビューコントローラで処理されたデータを埋め込む、テンプレートHTMLファイル

 例えば

http://cake/samples/view/3

 というURLの場合(標準的な動作)、以下の通りとなります。この処理はどのような流れで実現されているのでしょうか。

http://cake/samples/view/3で読み込まれるクラス
クラスファイル読み込まれるクラス名、説明
モデルsample.phpSampleクラス(DBのsamplesテーブルとその関連テーブルにアクセス)。
コントローラsamples_controller.phpSamplesControllerクラス(その中のview($id)メソッドが実行される。$idは3になる)。
ビューview/samples/view.thtmlデータは単なるHTML。コントローラからのデータをこのテンプレートに読み込んで表示。

htaccess(mod_rewrite)の基礎知識

 Apacheの「mod_rewrite」とは、「要求されたURLをリアルタイムで書き換えるための、ルールベースの書き換えエンジン」で、「URLを操作するためのスイス製のアーミーナイフ」ともマニュアルに書かれています。つまり、PHPが処理する前にURLを必要に応じて柔軟に書き換えることができる、アーミーナイフのように便利なモジュールです。指示する内容は「httpd.conf」に書くことができますが、「.htaccess」というファイルで設定することもできるようになっています。CakePHPの中には、

  1. 「CakePHP」ディレクトリを展開した直下に「.htaccess」がひとつ
  2. 「app」ディレクトリに「.htaccess」
  3. 「app/webroot」ディレクトリに「.htaccess」

 という3カ所に存在しています。なお、単に解凍してそのまま配置しただけなのに、「文字は表示されたけど画像が出ない」とか、「index.php?url=という形ではアクセスできるけど、/コントローラ/メソッド、という形ではうまく表示されない」などのトラブルが起きる場合、その大半は、Apacheの「mod_rewrite」が正しく動いていないことが原因です。phpinfo()などで、「mod_rewrite」モジュールが正しく読み込まれていることを確認してください。

設定項目のヒント(CakePHPに関係するオプション)
オプション説明備考
RewriteEngine OnURL書き換えエンジンをONにする。
RewriteCond指定した条件に当てはまる場合に、次行のRewriteRuleを実行する。-f 指定されたパス、ファイルが存在していればtrue。%{REQUEST_FILENAME}リクエストされたファイル名。
RewriteBaseCakePHPには指定がありませんが、サーバのディレクトリがAliasなどを使用して設定されている場合、物理的なファイル名のパスの指定をこれで追加してください。
RewriteRule正規表現で書き換えルールを設定します。[L](last) 指定条件にマッチすると、その後に続くRewriteRuleは評価されません。[QSA](query string append) 正規表現で置換文字列を置き換えるのではなく、クエリー文字列部分を追加します。
正規表現に関するヒント
記号説明
^行頭
$行末
.任意の1文字
[abcd]カッコ内の文字(a,b,c,d)が該当
[^abcd]カッコ内の文字以外(a,b,c,d以外)が該当
A|BAかB
+直前の文字の1回以上の繰り返し
?直前の文字の0回または1回の繰り返し
*直前の文字の0回以上の繰り返し
$1パターンの()で囲まれた最初の部分を$1で参照できます

 それでは、CakePHPの「.htaccess」ファイルを見てみましょう。

  1. 「CakePHP」を展開した直下にある「.htaccess:」
  2. <IfModule mod_rewrite.c>
       RewriteEngine on
       RewriteRule    ^$ app/webroot/    [L]
       RewriteRule    (.*) app/webroot/$1 [L]
    </IfModule>
    
  3. 「app」フォルダにある「.htaccess:」
  4. <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteRule    ^$    webroot/    [L]
        RewriteRule    (.*) webroot/$1    [L]
    </IfModule>
    
  5. 「app/webroot」フォルダにある「.htaccess:」
  6. <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
    </IfModule>
    

 上記の3つを解説すると以下の通りになります。

1.Cakeの親ディレクトリへのアクセス
  • RewriteEngineをONにする。
  • コントローラの指定のないURL(つまり、http://cakeのパスで呼ばれた場合)には、「app/webroot/」とする(処理終了)。
  • 何か指定されていれば、それをすべて、「app/webroot/」の後に追加。(処理終了)
  • つまり、以下のように指定されている場合、
    http://cake/コントローラ/メソッド/パラメータ
    
    次のようにアクセスしたのと同じことになります。
    http://cake/app/webroot/コントローラ/メソッド/パラメータ
    
2.Cakeのappフォルダへのアクセス
  • RewriteEngineをONにする。
  • コントローラの指定のないURL(つまり、http://cake/appのパスで呼ばれた場合)には、「webroot/」とする(処理終了)。
  • 何か指定されていれば、それをすべて、「webroot/」の後に追加。(処理終了)
  • つまり、以下のように指定されている場合、
    http://cake/app/コントローラ/メソッド/パラメータ
    
    次のようにアクセスしたのと同じことになります。
    http://cake/app/webroot/コントローラ/メソッド/パラメータ
    
3.Cakeの「app/webroot」フォルダへのアクセス
  • RewriteEngineをONにする。
  • URLで指定されたディレクトリが存在している場合には処理を中止。
  • URLで指定されたファイルが存在している場合には処理を中止。
  • 指定されている文字列をindex.php?url=の形にして追加。処理中止。
  • つまり、以下のように指定されている場合、
    http://cake/app/webroot/コントローラ/メソッド/パラメータ
    
    次のようにアクセスしたのと同じことになります。
    http://cake/app/webroot/index.php?url=コントローラ/メソッド/パラメータ
    

 ここまでをまとめると、

http://Cakeのパス/コントローラ/メソッド/パラメータ

 という形でリクエストがあった場合、Cakeの親ディレクトリと「app」ディレクトリのどちらからでも、最終的には、

http://Cakeのパス/appディレクトリ
               /webroot/index.php?url=コントローラ/メソッド/パラメータ

 という形に変換されることになります。ためしに、index.php?url=で直接リクエストしても、Cakeのプロジェクトはそのまま動きます。この後、Dispacherクラスのdispachメソッドがこのパラメータを分解して必要なデータをそろえます。

注:mod_rewriteのない環境では?
 ちなみに、mod_rewriteを使用できない環境ではどうなるか、というと、Cakeを展開したディレクトリの直下にある「index.php」が「mod_rewrite」の肩代わりをします。
http://cakeのパス/index.php/コントローラ/メソッド/パラメータ
 という形でアクセスできます。しかし、htmlファイルに直接書き込まれているcssファイルや画像ファイルに関しては、パスを自動的に変更することはできないため、自分で該当ディレクトリを作成し、そこに移動させてください。また、「app/webroot」にある「index.php」は「mod_rewrite」の肩代わりはしないようなので、「mod_rewrite」を使えない場合には、ユーザにcakeの展開ディレクトリ直下からアクセスさせるようにしてください。

dispatchの動作

 dispatchメソッドの中では、まず、URLを分解します。

function dispatch($url, $additionalParams=array()) {
   $params = array_merge($this->parseParams($url), $additionalParams);

 ControllerのURL部分から、コントローラ名を作成します。camelizeとは、アンダーバーを取り除き、各単語の先頭文字を大文字にする処理です。

$ctrlName = Inflector::camelize($params['controller']);
$ctrlClass = $ctrlName.'Controller';

 Actionの指定がない場合には、indexアクションが実行されます。また、__で始まっているアクションはプライベートなものとして扱われます。

if (empty($params['action'])) {
    $params['action'] = 'index';
}

if((in_array($params['action'], $classMethods)
    || in_array(strtolower($params['action']), $classMethods)) 
    && strpos($params['action'], '_', 0) === 0) {
    $privateAction = true;
}

 このようにして、コントローラとアクションが決まると、処理は、Controllerクラスのコードが実行されます。Controllerクラスのコンストラクタではモデル名とビューのパスを決定します。Inflector::classifyは、「posts」から、「Post」を作り出すメソッドです。「inflector.php」ファイルの中には、命名規則にそった名前を作り出す関数が色々とあります。

if ($this->viewPath == null) {
    $this->viewPath = Inflector::underscore($this->name);
}
$this->modelClass = Inflector::classify($this->name);
$this->modelKey = Inflector::underscore($this->modelClass);

 その後、dispachは、$controller->constructClasses();として、Controllerクラスの下記のコードを呼び出します。これで必要なモデルが読み込まれていきます。loadModel()は、「cake\basics.php」の中にあります。

if ($this->uses) {
    $uses = is_array($this->uses) ? $this->uses : array($this->uses);

    foreach($uses as $modelClass) {

                :
                :省略
                :

        if(!class_exists($modelClass)){
            loadModel($modelClass);
        }
                :
                :省略
                :
    }
    return true;
}

 いかがだったでしょうか。フレームワークは「想定内」の作業では非常にスムーズに動きますが、フレームワーク「想定外」の作業をさせようとすると、そこからは誰も体験したことのない未知の世界です。オープンソースプロジェクトの場合は自分の疑問に対して誰かがすべて答えてくれるわけではありませんので、自力で原因を追究し解決するスキルも磨かなければなりません。そこから新たなテクニックが見つかる場合もあります。フレームワークの改善案を考えたら報告してみましょう。フレームワークの発展を助けることができるかもしれません。そして、記事を書いてみると自分の理解も深めることができます。

CakePHPを使ったプロジェクトも多数公開されています。
CakePHPを使ったプロジェクトも多数公開されています。

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

バックナンバー

連載:CakePHPチュートリアル

著者プロフィール

  • 堂園 俊郎(ドウゾノ シュンロウ)

    (株)コミュニケーション・ビジネス・アヴェニュー技術担当。著書「CakePHPガイドブック」。CentOSサーバによる大小のコールセンター立ち上げ業務のかたわら、オープンソースプロダクトのコンサルティングを行う日々。http://cakephp.jpの管理人。ブログ:「CakePHPのおいしい食べ方...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5