cakephpで作成したシステムのURLは一般的に https://example.com/cakephp設置ディレクトリ/コントローラー名/アクション名
のような形式になります。
しかしwebサーバー上には上記のようなファイルはありません。
それなのに何故、コントローラー、アクションで設定したhtmlにアクセスできるかを見ていきたいと思います。
cakephp設置ディレクトリ直下の.htaccessファイル
まず設置ディレクトリ直下にある.htaccessファイルによって、設置ディレクトリ/app/webroot/ へurlが書きかえれます。
RewriteEngine on RewriteRule ^$ app/webroot/ [L] RewriteRule (.*) app/webroot/$1 [L]
上記の表記によって、 https://example.com/cakephp_dir/controllers/action は https://example.com/cakephp_dir/app/webroot/controllers/action となります。
webrootディレクトリの.htaccessファイル
webrootにある.htaccessファイルでは次のような処理が行われます。
1. urlに実際にファイルがある場合は何もしない。
2. ファイルがない場合、次のようにurlを書き換える。
https://example.com/cakephp_dir/app/webroot/controllers/action => https://example.com/cakephp_dir/app/webroot/index.php?url=controllers/action
webroot以下のcssや画像ファイルにちゃんとアクセスできるのは上記の1の処理のおかげということになります。
実際にファイルがない場合はすべて、GETパラメーターにurl情報が渡された形でhttps://example.com/cakephp_dir/app/webroot/index.phpが起動します。
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
index.phpでの処理
index.phpでは基盤のファイル読み込み、各種設定後に、渡されたurl情報を解析してコントローラーとアクションを特定します。
//index.php内でDispatchオブジェクトが生成され、dispatchメソッドが実行される。 //index.php内 if (isset($_GET['url']) && $_GET['url'] === 'favicon.ico') { return; } else { $Dispatcher = new Dispatcher(); $Dispatcher->dispatch(); } //dispatch内でurlが解析される ・・・ } else { if ($url) { $_GET['url'] = $url; } $url = $this->getUrl(); $this->params = array_merge($this->parseParams($url), $additionalParams); } $this->here = $this->base . '/' . $url; ・・・ //コントローラーに各種パラメーターが設定される $controller =& $this->__getController(); ・・・ $controller->base = $this->base; $controller->here = $this->here; $controller->webroot = $this->webroot; $controller->plugin = isset($this->params['plugin']) ? $this->params['plugin'] : null; $controller->params =& $this->params; $controller->action =& $this->params['action']; $controller->passedArgs = array_merge($this->params['pass'], $this->params['named']); if (!empty($this->params['data'])) { $controller->data =& $this->params['data']; } else { $controller->data = null; } ・・・ // _invokeにコントローラーとパラメーターを渡す。 return $this->_invoke($controller, $this->params); //_invoke内で controller->render() を実行し、実行結果を出力 //コントローラーで設定した処理が実行される $output = call_user_func_array(array(&$controller, $params['action']), $params['pass']); if ($controller->autoRender) { $controller->output = $controller->render(); } elseif (empty($controller->output)) { $controller->output = $output; } ・・・ echo($controller->output);
上記のような流れでコントローラーに設定した処理が実行され、htmlがレンダリングされます。