(cakephp)コンポーネントの有効無効を行う enabled プロパティ
コントローラーの components プロパティに沿って、コンポーネントが読み込まれますが、コンポーネントの 「startup」「beforeRender」「beforeRedirect」「shutdown」メソッドを実行する際、各コンポーネントの enabled プロパティがチェック($component->enabled === true)され、各メソッドの実行を制御できます。
おさらい:例として、アクセスから Auth コンポーネントの認証まで
- ソースは cakephp 1.3.2 より
- projects コントローラーの add アクションは認証が必要な処理
「projects/add」にアクセス、mod_rewrite で「/index.php?url=projects/add」に振り替えが行われます。
[app/webroot/index.php]
- コアライブラリ等を読み込み、Dispatcher::dispatch() に処理が移ります。
[cake/dispatcher.php]Dispatcher::dispatch
- ルーティングを行い( $this->params )、projects コントローラーのインスタンス を作成( $controller )します。
- $this->_invoke($controller, $this->params); に処理が移ります。
[cake/dispatcher.php]
<?php function _invoke(&$controller, $params) { // モデルを読み込みとコンポーネントの読み込みを行います。 $controller->constructClasses(); // ・コンポーネントの初期化(Component::initialize)、 // ・controller::beforeFilter の実行、 // ・コンポーネントの実行($this->Component->triggerCallback('startup', $this)) // を行います。 $controller->startupProcess(); //以下略 }
まずは、
$controller->constructClasses() を詳しく見て、
その後、
$controller->startupProcess() を詳しく見ます。
[cake/libs/controller/controller.php]
<?php function constructClasses() { $this->__mergeVars(); // ここで、コンポーネントの読み込みが行われます。 $this->Component->init($this); // これ以降は、モデルの読み込みのため、略。 }
$this->Component->init($this); を詳しく見ます。
[cake/libs/controller/component.php]
<?php function init(&$controller) { if (!is_array($controller->components)) { return; } $this->__controllerVars = array( 'plugin' => $controller->plugin, 'name' => $controller->name, 'base' => $controller->base ); // ここでコンポーネントの実際の読み込みが行われます。 $this->_loadComponents($controller); } function _loadComponents(&$object, $parent = null) { // ここまで略 if ($parent === null) { // $this->_primary は、読み込んだコンポーネント名のリストです。 // 例 : array('Security', 'Auth', 'Session') $this->_primary[] = $component; } if (isset($this->_loaded[$component])) { // 略 } else { if ($componentCn === 'SessionComponent') { $object->{$component} =& new $componentCn($base); } else { $object->{$component} =& new $componentCn(); } // ここで、enabled プロパティが設定されます。 // これの問題点は後述。 $object->{$component}->enabled = true; // $this->_loaded は、読み込んだコンポーネントのリストです。 // 例 : // array( // 'Security' => object(SecurityComponent), // 'Auth' => object(AuthComponent), // 'Session => object(SessionComponent), // ) $this->_loaded[$component] =& $object->{$component}; if (!empty($config)) { $this->__settings[$component] = $config; } } }
[cake/libs/controller/controller.php]
<?php function startupProcess() { // コンポーネントの初期化 // *Controller->components にあるコンポーネントクラスの初期化を実行します。 $this->Component->initialize($this); // *Controller::beforeFilter の実行 // ここでは、 ProjectsController::beforeFilter を実行します。 // 「$this->Auth->allow('index', 'view');」 が記述してあるとし、 // Auth コンポーネントに認証を必要としないアクションは、 「index」「view」であることを伝えます。 // つまり、「add」アクションは、認証が必要なアクションとなります。 $this->beforeFilter(); // コンポーネント startup メソッドを実行します。 // beforeFilter の後、コントローラーアクションの前に呼ばれます。 $this->Component->triggerCallback('startup', $this); }
$this->Component->triggerCallback('startup', $this)) を詳しく見ます。
[cake/libs/controller/component.php]
<?php // コンポーネントの為の call_user_func() のようなコールバック関数をコールするメソッドです。 function triggerCallback($callback, &$controller) { // $this->_primary は、読み込んだコンポーネント名のリストです。 // 例 : array('Security', 'Auth', 'Session') // $this->_loaded は、読み込んだコンポーネントのリストです。 // 例 : // array( // 'Security' => object(SecurityComponent), // 'Auth' => object(AuthComponent), // 'Session => object(SessionComponent), // ) foreach ($this->_primary as $name) { // コンポーネントインスタンスを取得します。 $component =& $this->_loaded[$name]; // $component->enabled は、 // コンポーネントの読み込み時に、強制的に設定される値(true)です。 // ここでは、 // controller::beforeFilter で、コンポーネントの有効無効を設定できます。 // 問題点 : enabled プロパティの存在が気づきにくい。 // API 集に基本的に記載なし、 // 元々、 // コンポーネントクラスやその親の Object クラスにもプロパティが書かれていないため、気づきにくい。 // ・RequestHandlerComponent には、プロパティがあるので類推する「var $enabled = true;」 // ・[cake/libs/controller/component.php]のソースを読む // ・英語版 cake book の 3.6.2 Configuring Components の // 「You can disable the callbacks triggering by setting the enabled property of a component to false.」 // の1行を見逃さない。(執筆時、日本語版には記載がなかった) // のいずれかで判別する必要がある。 // $component クラスに 'startup' メソッドがあり、コンポーネントが有効になっている場合、 // startup メソッドを実行する。 // ここで、AuthComponent::startup が呼ばれることになる。 if (method_exists($component, $callback) && $component->enabled === true) { $component->{$callback}($controller); } }
AuthComponent::startup を詳しく見ます。
[cake/libs/controller/components/auth.php]
<?php function startup(&$controller) { // この中で、認証処理 // 略 }
その他
enabled プロパティを使って、Authコンポーネントのパスワードハッシュ化回避を行おうと試みるものの、
startup メソッドをトレースすることになるので、 意味なかった(´・ω・`)