コンポーネントには以下のコールバックメソッドがあります。
- initialize(Controller $controller)
- startup(Controller $controller)
- beforeRender(Controller $controller)
- shutdown(Controller $controller)
- beforeRedirect(Controller $controller, $url, $status=null, $exit=true)
いずれのコールバックメソッドも引数にコントローラを持っているので、コンポーネントからコントローラのプロパティやメソッドにアクセスできます。
例えばコントローラのbeforeFilterの前に実行されるinitializeメソッドで以下のように書けば、コンポーネントの別のメソッドでもコントローラにアクセスできるわけです。
HogeComponent
public function initialize(Controller $controller) {
$this->controller = $controller;
}
public function test() {
// Viewに変数を渡したり
$this->controller->set('title_for_layout', 'Hogeコンポーネントのtestメソッドからセットしたタイトル');
// Sessionメッセージを設定したり(セッションコンポーネントをコンポーネントでセットすればコントローラを通さなくてもいいけど)
$this->controller->Session->setFlash('Hogeコンポーネントのtestメソッドからセットしたメッセージ');
// Modelも使えます。(App::usesで呼ぶ方がスマートだけど)
$this->controller->loadModel('Test');
}
ところが、コントローラでコンポーネントを読み込む場合はちょっと問題があります。
例えば呼び出し元コントローラのあるメソッドでこんな風にHogeコンポーネントを読み込む場合。
class FugasController {
function aru() {
$this->Hoge = $this->Components->load(Hoge);
}
}
この場合、コンポーネントのコールバックメソッド「initiazile」と「startup」は通すことができません。*1
コンポーネント側の通常のメソッドを、コントローラを使用する前提で作ったりすると困ったことになるわけです。
コンポーネントのコンストラクタで呼出元コントローラをセットする
そこで、コンストラクタを使って呼び出し元コントローラをプロパティにセットすることにしました。
HogeComponent
public function __constract(ComponentCollection $collection) {
$this->controller = $collection->getController();
}
コンストラクタの引数はコントローラではなくComponentCollectionであることに注意しましょう。
ComponentCollectionは呼び出し元のコントローラを_Controllerプロパティに持っていますが、protectedのためHogeComponentからはアクセスできません。
なので、getControllerメソッドを使って取得しています。
コントローラ単位でコンポーネントをセットするのは勿体無い、だけどコントローラにもアクセスしたい。というのはよくあるケースだったのでφ(..)メモしておきます。
- どちらのメソッドもFugasコントローラのaruメソッド実行前に呼出が終わっているから [↩]
