d.hetima RSSフィード

2006-08-28 CakePHPの処理の流れを追ってみよう

CakePHPの処理の流れを追ってみよう(0)

このシリーズは2006年8月28日の日記に追記していくかたちで書いていこうと思います。RSSの出力がどうなるか分かりませんが、1ページで俯瞰できる便利さを取ります。

第2回はcake/bootstrap.phpの中身です。

CakePHPの処理の流れを追ってみよう(1)

URLをリクエストしてから、実際に書いたコ−ドに辿り着くまでを追ってみます。掲載しているコード(のようなもの)は分かりやすくするために省略化したフローチャート的なもので、文法などはまったく考慮していません。分かりやすくなっているかは分かりません。また、正確にトレースできているのかも保証できません(´д`;)。

それでは入り口のindex.phpから。

app/webroot/index.php

define ROOT, APP_DIR, CAKE_CORE_INCLUDE_PATH, WEBROOT_DIR, WWW_ROOT, CORE_PATH, APP_PATH
{
    ROOT = '/path/to/cake'
    APP_DIR = 'app'
    CAKE_CORE_INCLUDE_PATH = ROOT
    WEBROOT_DIR = 'webroot'
    WWW_ROOT = 'cake/app/webroot/'
    
    if(ini_set){
        'include_path' += CAKE_CORE_INCLUDE_PATH + ROOT/APP_DIR/
    }else{
        APP_PATH = ROOT/APP_DIR/
        CORE_PATH = CAKE_CORE_INCLUDE_PATH/
    }
}

require CORE_PATH.'cake/bootstrap.php';
$Dispatcher=new Dispatcher();
$Dispatcher->dispatch();

まず各フォルダをdefineしています。

ini_set関数が使える場合、APP_PATHとCORE_PATHは使わずにinclude_pathに追加しています。requireやincludeではAPP_PATHやCORE_PATHが定義されている場合はフルパスで、そうでない場合は相対パスをinclude_pathから探すようになっています。上手いことやってますね。実質ini_set()が実行されAPP_PATHとCORE_PATHはnullになり、「cake内のファイルをapp内にコピーするとapp内のファイルを読み込む」仕様を実現しています(追記:とか思ってたらapp_model.phpはfile_existsでif分岐してrequireしてました) (参考:CakePHPのおいしい食べ方 - ディレクトリ構造2(つぼを知る))。

準備ができたらcake/bootstrap.phpをrequire、Dispatcherを作ってdispatch()メソッドを呼び終了。


cake/bootstrap.phpでは多くのファイルをrequireしています。

URLの調節をなんかやってるようです。

最後にキャッシュが有効になっている場合、viewのrenderCache()を呼び出します。キャッシュが正常に出力されたらdie()するので、後の$Dispatcher->dispatch();は呼ばれずにここで終了します。

cake/dispatcher.php

dispatch() {
    $params = $this->parseParams();
    $params['controller']
    $params['action']
    loadController();
    if($params['plugin']){
        loadPluginModels();
    }
    $controller =& new $ctrlClass();
    $controller->変数いろいろ = 値いろいろ;
    $controller->_initComponents();
    $controller->constructClasses();
    return $this->_invoke();
}

function _invoke(&$controller, ...){
    $this->start(){
        $controller->beforeFilter();
        $controller->components->startup();
    }
    $controller->$params['action']; //call action
    if ($controller->autoRender) {
        $output = $controller->render();
    }
    $controller->afterFilter();
}

dispatch()の最初にparseParams()を呼びリクエストを解析しています(ここでapp/config/routes.phpを読み込んでます)。これでどのcontrollerのどのactionを呼ぶかが決定され、後は怒濤のセットアップ、action実行、後始末。

とりえずcontrollerのaction部分まで辿り着きました。

CakePHPの処理の流れを追ってみよう(2)

今回はbootstrap.phpの中身を簡略化してみます。

cake/bootstrap.php

require 'cake/basics.php';        //関数いっぱい
require 'app/config/core.php';    //基本的な設定のdefine
require 'cake/config/paths.php';  //フォルダのdefineいっぱい

require /* cake/libs/内の */ 'object.php', 'session.php', 'security.php',
        'neat_array.php', 'inflector.php', 'configure.php';
//これらはすべてクラスファイルなので、この場で実行されるコードは記述されていない。

$paths = Configure::getInstance();
//この過程で/app/config/bootstrap.phpがrequireされる

ここでなんかURLを調べてる。

require 'cake/dispatcher.php';
//model関連の初期化
require 'cake/libs/model/connection_manager.php';
require 'config/database.php'; //←config('database');
require 'cake/libs/model/model.php';
loadModels(){
    require app_model.php
    //ここでModelを全部読み込んでいるようだ。
    require models in /app/models/ and $modelPaths
}

//キャッシュ関連の処理
if(CACHE_CHECK){
    $view->renderCache();
}

これまでの流れをまとめるとこんな感じです。

index.php{
    define ディレクトリ構造
    bootstrap.php{
        define 基本設定
        require 基本クラス
        init model
        if(cache){ renderCache }
    }
    $Dispatcher->dispatch(){ //dispatcher.php
        parse
        beforeFilter
        action!!
        render
        afterFilter
    }
}