はじめに

CakePHPで何らかのオブジェクトを操作する場合、対象となるオブジェクトの種類やどこからアクセスするかによって方法が異なる場合があり、それ以前にそもそもインスタンス化されていないことを知らずにアクセスしようと無謀な挑戦を試みたりすることがあります・・・よね?自分の経験上、始めたばかりの時はここで躓くことが結構多く、今でも分からずに調べることが多いですし、あまり使っていないと同じ事を何度も調べたりもしてしまいます。このエントリは、あるオブジェクト「に」あるオブジェクト「から」アクセスする方法について調べたものの備忘録です。

  • 初心者のかたはどうぞ「 初心者の方へ 」にまず目を通してください。
  • 内容は適宜追加・修正される可能性があります。
  • すべてCakePHP2系の情報です。1系の情報が今後追加されることはありません。
  • 可能な限り公式ドキュメントへのリンクを張っています。日本語訳のある場合はそれも併記しています。特に参考にさせていただいたブログなどは、そのリンクも張っています。

目次

初心者の方へ

ここに書かれてある内容は、調査資料のようなものであり、一般的に推奨されていない内容も含まれている可能性が高いです。推奨/非推奨の線引きは私の力量を超えているためここでは行なっていません。

例えば Model へのアクセスは基本的にどこからであろうとも ClassRegistry::init でアクセスできますので、このエントリにはその旨が記載されています。しかしそのことが同時に、どこからであろうともModelを好きに呼び出して良い、ということを意味しているわけではありません。つまり HelperクラスからModelを呼び出して良いのか(…個人的には有りだと思っていますが…)などというのは別の議論になります。

というわけで、 通常のやり方を把握する目的でこのエントリの内容を用いるのはオススメ出来ません

私の場合がそうだったのですが、ひと通りCakePHPの使い方を学んで自分なりの実装をしたいと思った時に、オブジェクトの取り扱いに悩まされがちです。「このオブジェクトをここで扱うにはどうしたら良いのだろうか?」と。そんなとき、完成を急ぐあまり自分勝手に仕様を無視したくなる誘惑に駆られますが、そこで規約から外れてしまうとあとで大変な目に会うことがあります・・・。CakePHP には CakePHP のやり方があって、基本はそれにそってオブジェクトの呼び出しをすべきであり、場合によってはそこでそのオブジェクトを呼び出すことが適切でない場合もあり、そもそもタイミング的にオブジェクト化されていないことさえあります。

そこで、何らかのオブジェクトをそれまでとは違うやり方で扱いたいと思った場合、(このエントリを読む前に)まずドキュメントを読む、あるいはコアのコードから近いような処理を探すのが良いと思います。 CakeDC(CakePHPのコア開発者の多くが参加している企業)製のプラグイン も、十分に仕組みを熟知したエキスパートの手によるものなので安心して参考にできると思います。

そして調べる際に最初にするべきことは「何に」「何から」アクセスするかを明確にすることです。具体的にはそのオブジェクトのクラス(およびその基底クラス)が何であるかです。呼び出し先と呼び出し元が明らかにならないことには適切な方法を見いだせません。

特に「何から」アクセスしているかについてのチェックポイントは次のようなものがあります

  1. アクセス元のクラスだけでなく、それが何を継承しているのかも把握しましょう。親クラスで既にアクセス方法が確立していないかを知るためです。
  2. エレメントやレイアウトを含むテンプレートファイルは、Viewクラスのインスタンス内に展開されていることを知りましょう。端的に言うとテンプレートに記述した $this は、今まさにレンダリングを行なっている最中の View オブジェクトです。

オブジェクトへのアクセスの段階的検討

オブジェクトへのアクセスを調べる際に、次のような段階別の分類を意識すると良いのではないかと思っており、このエントリの作成にあたっては以下の方針で検討しました。

1.フレームワークが自動的にセットしているかどうか

幾つかのオブジェクトへの参照は、あるオブジェクトが生成されてから特定のタイミングで自動的にフレームワークがセットする場合があります。あるオブジェクトを参照したい場合はこれをまず調べる必要があります。調べるにあたっては公式ドキュメントが役に立ちますが、ソースコードを読むことのほうが確実で安心できるかも知れません。このとき基底クラスも忘れずに調べます。ルートとなる継承元まで辿っていきます。最初は面倒ですが、そのうち慣れます。そして、すでにアクセスが用意されているものは速やかにその手法を採択すべきです。

何故あるオブジェクトへの参照は可能なのに別のオブジェクトへの参照はないのか疑問に思うことも多いかも知れません。CakePHPの基本動作を成し遂げるために必然的に行なっているように見える場合もあれば、単に利用者に便宜をはかるために行なっているように見える場合もあります。ですが、多くの(ひょっとしたらすべての)場合はCakePHPというフレームワークの開発の理念に基づくものではないかと思っています。この辺りは文句を言うのではなく、そういう仕様だと受け入れることが良い付き合い方だと思います。

2.そのオブジェクトを呼び出すために用意されたAPIがあるかどうか

参照元のオブジェクトに自動的にセットされたものでない場合、そのオブジェクトを呼び出すためのAPIが用意されているかを調べる必要があります。APIが用意されている場合、基本的にはそのAPIを利用します。独自のインスタンス化は後で泣きを見ることがあります。一番の問題は、何かことが起こってからその原因を履き違えて、CakePHPの仕様に問題があると勘違いしてしまい、正しい方法にたどり着くことを自ら放棄してしまうことです。

3.それでも見つからないなら

ここから先は適宜対応ということになります。1か2で見つからないなら、ソースコードで似たような処理をしていないか grep などを使って調べます。ただし見つかったからといって同じ手法が使えるかどうかは状況により異なります。

バックエンドではどこでどのようにインスタンス化されているか?

アクセスしたいオブジェクトがCakePHPのコアの働きにより自動的に生成されている場合、それがどこでどのように生成されているのでしょうか。ざっくりと見てみましょう。

ここでは一般的と思われる処理の流れに従って、実際にインスタンスの生成が 「完了する」 順に記載して最初の記事を書きました。大体の流れをつかめるのではないかとそのような形式にしたのです。

例えばComponentCollection の生成は Controller のコンストラクタでなされるため、以下の表では Controllerより先に記述しています。

・・・しかし、その後いくつか追加するにつれ、上述したようなやり方が破綻してきたため、とりあえず追加分は表の下に加えていってます。

クラス名
(*)はそのサブクラス
生成される場所 コード抜粋
Dispatcher index.php
// webroot/index.php
App::uses('Dispatcher', 'Routing');
$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(new CakeRequest(), new CakeResponse(array('charset' => Configure::read('App.encoding'))));
CakeRequest index.php
CakeResponse index.php
ComponentCollection Controller::__construct
// Dispatcher::dispatch > Dispatcher::_getController > ReflectionClass::newInstanceController::_construct() 
$this->Components = new ComponentCollection();
Controller (*) Dispatcher::_getController
// Dispatcher::dispatch > Dispatcher::_getController($request, $reqponse)
$ctrlClass = $this->_loadController($request); $reflection = new ReflectionClass($ctrlClass);
return $reflection->newInstance($request, $response);
Component (*) ComponentCollection::load()
// Dispatcher::dispatch > Dispatcher::_invoke > Controller::constructClasses > ComponentCollection::init > ComponentCollection::load
// ComponentCollection::load($component, $settings = array())
list($plugin, $name) = pluginSplit($component, true);
if (!isset($alias)) {
    $alias = $name;
}
//-- 略 --
$componentClass = $name . 'Component';
//-- 略 --
$this->_loaded[$alias] = new $componentClass($this, $settings);
DATABASE_CONFIG ConnectionManager::_init()
// ConnectionManager::_init()
self::$config = new DATABASE_CONFIG();
Model (*) ClassRegistry::init
// ClassRegistry::init($class, $strict = false)
$reflection = new ReflectionClass($class);
//-- 略 --
if ($reflection->getConstructor()) {
    $instance = $reflection->newInstance($settings);
} else {
    $instance = $reflection->newInstance();
}
//-- 略 --
// 上記のリフレクションでインスタンスの生成が出来ていない場合 $appModel = 'AppModel';
//-- 略 --
$instance = new $appModel($settings);
//-- 略 --
$_this->map($alias, $class);
BehaviorCollection Model::__construct()
public function __construct($id = false, $table = null, $ds = null) {
//-- 略 --
$this->Behaviors = new BehaviorCollection();
//-- 略 --
$this->Behaviors->init($this->alias, $this->actsAs);
}
Behavior (*) BehaviorCollection::load()
// ClassRegistry を用いることで、 Model - Behavior の多対多関係を実現
public function laod($behavior, $config = array()) {
    //-- 略 -- ここまでに $plugin, $class, $alias を適宜展開済み
    App::uses($class, $plugin . 'Model/Behavior');
    //-- 略 --
    if (!isset($this->{$alias})) {
        if (ClassRegistry::isKeySet($class)) {
            // 生成済みのインスタンスは ClassRegistry から取得
            $this->_loaded[$alias] = ClassRegistry::getObject($class);
        } else {
            $this->_load[$alias] = new $class();
            // 生成したインスタンスを ClassRegistry に登録
            ClassRegistry::addObject($class, $this->_loaded[$alias]);
            if (!empty($plugin)) {
                ClassRegistry::addObject($plugin . '.' . $class, $this->_loaded[$alias]);
        }
    }
}
}
DataSource (*) ConnectionManager::getDataSource()
public static function getDataSource($name) {
    if (empty(self::$_init)) {
        self::_init();
    }
    if (!empty(self::$_dataSources[$name])) {
        $return = self::$_dataSources[$name];
        return $return;
    }
    if (empty(self::$_connectionsEnum[$name])) {
        self::_getConnectionObject($name);
    }
    self::loadDataSource($name);
    $conn = self::$_connectionsEnum[$name];
    $class = $conn['classname'];
    self::$_dataSources[$name] = new $class(self::$config->{$name});
    self::$_dataSources[$name]->
    configKeyName = $name;
    return self::$_dataSources[$name];
}
HelperCollection View::__construct
public function __construct(Controller $controller = null) {
    //-- 略 --
    $this->Helpers = new HelperCollection($this);
    //-- 略 --
}
View Controller::render
public function render($view = null, $layout = null) {
    //-- 略 --
    $viewClass = $this->viewClass;
    //-- 略 --
    $View = new $viewClass($this);
    //-- 略 --
    $this->View = $View;
    //-- 略 --
}
Helper (*) HelperCollection::load()
public function load($helper, $settings = array()) {
    //-- 略 --
    list($plugin, $name) = pluginSplit($helper, true);
    //-- 略 --
    $helperClass = $name . 'Helper';
    //-- 略 --
    $this->_loaded[$alias] = new $helperClass($this->_View, $settings);
    //-- 略 --
}
(参考)テンプレートファイル View::_evaluate()
// オブジェクトの生成ではありません
protected function _evaluate($viewFile, $dataForView) {
    $this->__viewFile = $viewFile;
    extract($dataForView);
    ob_strat();
    include $this->__viewFile;
    unset($this->__viewFile);
    return ob_get_clean();
}
CakeRoute(*) Router::connect()
// Router::connect()
public static function connect($route, $defaults = array(), $options = array()) {
    //-- 略 --
    self::$routes[] = new $routeClass($route, $defaults, $options);
    //-- 略 --
}

 

Modelオブジェクトへアクセスする

Modelのオブジェクトへはどのオブジェクトからでもアクセスできます。まず自身のプロパティとしてセットされていないかを調べ(—さらに自身のプロパティの参照先を調べてもいいかも知れません–)、見つからない場合は ClassRegistry::init を用います。

ModelオブジェクトからModelオブジェクトへアクセスする場合

モデルからモデルへアクセスする場合、アクセス元のモデル自身にアクセス先のモデルオブジェクトへの参照がセットされていないかを調べます。具体的にはアソシエーションを設定しているかどうかです。次の例においては、アソシエーションを張ったモデルへのインスタンスを自身のプロパティとして参照できます。

サンプルコード

/**
 * app/Model/Post.php
 * Post class
 */
class Post extends AppModel {
    public $hasMany = array( 'Comment' );
    public $belongsTo = array(
        'Category',
        'Author' => array(
            'className' => 'User',
            'foreignKey' => 'user_id',
        ),
    );
    public function myBusiness() {
        // Comment, Category, User クラスの各インスタンスへ
        // 自身のプロパティとしてアクセスできる
        $comment = $this->Comment->find('first');
        $category = $this->Category->find('first');
        $author = $this->Author->find('first'); // User クラスのインスタンス。エイリアスは 'Author'
    }
}

Controller オブジェクトからModelオブジェクトへアクセスする場合

コントローラからモデルオブジェクトへアクセスする場合、コントローラオブジェクト自身にモデルオブジェクトへの参照がセットされていないかをまず調べます。デフォルトで、CakePHPは自動的にコントローラに対してプライマリモデルとして一つのモデルクラスのインスタンスをセットします。

サンプルコード

PostsController extends AppController{ }

この場合、Postクラスのインスタンスには、 $this->Post としてアクセスします。

また、デフォルトモデル以外のモデルクラスを自動的に利用可能に設定することも可能です。PostsController で自動的に Calendar モデルにアクセス可能にするには Controller::$uses プロパティに対し、次のように設定します。

class PostsController extends AppController {
    public $uses = array('Calendar');
    // $this->Calendar でアクセス可能
    // ただし、 $this->Post の自動設定は効力を失う
}

Controller::$uses プロパティを指定する場合、その配列に含まれるモデルに対して自動的にアクセスが可能になります。ただしこの場合 Post モデルへの自動アクセスは暗黙的に行われることはなく失効していることに注意してください。

また、Component の名称と衝突した場合は Component が優先され、 Model への参照は失われます。

Behavior オブジェクトから Model オブジェクトへアクセスする場合

Behavior のメソッドが Model のビヘイビアとして背後に隠蔽されて振る舞う場合、そのメソッドの第一引数に Model オブジェクト参照を受け取ります。通常はその引数にアクセスすることで処理を行います。Behavior は一つのインスタンスで複数のModelオブジェクトを捌かなくてはならないことに注意しましょう。

Viewオブジェクトへアクセスする

テンプレートファイルからViewオブジェクトへアクセスする場合

エレメントやレイアウトを含むすべてのテンプレートファイルは、Viewオブジェクトの_evaluateメソッド内にインクルードされることによりレンダリングされます。したがってこれらのテンプレートファイルからレンダリング中の Viewオブジェクト へは $this を用いて自身を参照することでアクセスします。

サンプルコード[app/View/Posts/index.ctp]

// テンプレートファイルに記述した $this はViewクラスのインスタンスである
echo $this->element('foo');

HelperオブジェクトからViewオブジェクトへアクセスする場合

HelperオブジェクトからViewオブジェクトへアクセスするには Helper::$_View を用います。

サンプルコード [Cake/View/Helper/CacheHelper]

class CacheHelper extends AppHelper {
    public function afterLayout($layoutFile) {
        if ($this->_enabled()) {
            $this->_View->output = $this->cache($layoutFile, $this->_View->output);
        }
        // ...略...
    }
}

Controller から View へ渡された値は View::getVar() や View::$viewVars でアクセスできるため、以下のように参照できます。

サンプルコード[Cake/View/Helper/FormHelper]

class FormHelper extends AppHelper {
    protected function input($fieldName, $options = array()) {
        // ...略...
        $varName = Inflector::variable(Inflector::pluralize(preg_replace('/_id$/', '', $fieldKey)) );
        $varOptions = $this->_Viewe->getVar($varName);
        // ...略...
    }
}

それ以外の場所からViewオブジェクトへアクセスする(ただし、Controller::render() 以降)

View がインスタンス化される箇所は Controller::render においてです。この際、インスタンスは必ず新規に作成されるため、それ以前に何らかの方法でこれにアクセスすることは不可能です。

Controller::render 以降であれば、Controller のインスタンスを経由して $View プロパティとしてアクセスできます。

Controllerオブジェクトへアクセスする

ComponentオブジェクトからControllerオブジェクトへアクセスする場合

Component オブジェクトから Controller オブジェクトへアクセスするにはComponentクラスのコールバックを利用するか、__constructで渡される ComponentCollection オブジェクトのgetController メソッドを用います。

Behavior が ひとつのインスタンスで複数の Modelオブジェクトを扱うのとは対照的に、一つのComponentのインスタンスは通常一つのControllerインスタンスしか扱いません。そのため、例えば __construct() や Component::startup で取得した Controllerオブジェクト への参照を自身のプロパティとしてセットし、その他のメソッドでそれを同一のインスタンスとして暗黙的に扱うことがコアコードを見る限りは許されています。

サンプルコード [ Cake/Controller/Component/PaginatorComponent ] (※ __construct の時点であらかじめ $Controller としてセットしている例です。コアのコンポーネントでは、この PaginatorComponent が唯一プロパティにコントローラへの参照をセットしています。)

class PaginatorComponent {
    public function __construct(ComponentCollection $collection, $settings = array()) {
        // ...略...
        // ComponentCollection::getController() で Controllerオブジェクトを取得し、メンバー変数にセット
        $this->Controller = $collection->getController();
        // ...略...
    }
    public function paginate() {
        // ...略...
        // 実行中の Controller::paginate() から、
        // (暗黙的に)同じインスタンスの $this->Controller に対して処理を行なっている
        $this->Controller->request['paging'] = array_merge( 
            (array)$this->Controller->request['paging'],
            array($object->alias => $paging)
        );
        // ...略...
    }
}

Componentのコールバックメソッドには次のものがあります

  • initialize(Controller $controller)
  • startup(Controller $controller)
  • beforeRender(Controller $controller)
  • shutdown(Controller $controller)
  • beforeRedirect(Controller $controller, $url, $status = null, $exit = true)

コールバックメソッドのパラメータで渡されるコントローラのオブジェクトにアクセスする例

class AuthComponent {
    public function initialize(Controller $controller) {
        $this->request = $controller->request;
        $this->response = $controller->response;
        $this->_methods = $controller->methods;
        if (Configure::read('debug') > 0) {
            Debugger::checkSecurityKeys();
        }
    }
}

Controllerのアクションを間接的にコールする場合

それ以外で(リクエストを処理している)Controllerのインスタンスを直接操作するためのAPIはありません。ただし、任意のURLを引数にした Controllerのアクションを呼び出す方法として Object::requestAction() メソッドが用意されています。このメソッドを用いることで、コントローラのアクションを Dispatcher::dispatch() を通して間接的にコールすることができます。なおこのときコールされるコントローラのアクションは パラメータのURLを Router::reverce で解析した結果が選択されるため、根本的にルーティングの設定に影響を受けます。

サンプルコード [ Cake/Controller/Component/RequestHandlerComponent ]

class RequestHandlerComponent {
    public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true) {
        // ...略...
        $this->response->body($this->requestAction($url, array('return', 'bare' => false)));
        // ...略...
    }
}

Controllerのインスタンスを直接生成する場合

テストケースやエラーハンドリングにおいてControllerのモックアップが必要な場合は直接 new します。

サンプルコード [Cake/Error/ExceptionRenderer]

class ExceptionRenderer {
    protected function _getController($exception) {
        // ...略...
        if (empty($controller)) {
            $controller = new Controller($request, $response);
            $controller->viewPath = 'Errors';
        }
        // ...略...
    }
}

Shellオブジェクトへアクセスする

—調査中—

Behaviorオブジェクトへアクセスする

Behaviorをオブジェクトとして操作するには ClassRegistry::getObject を用います。

ただしBehaviorはModelの動作を補完するためのものであり、通常はそれをModelからオブジェクトとして操作するのではなく、パラメータを渡すことにより振る舞いをコントロールします。

(※テストケース以外で Behavior オブジェクトを操作する必要にかられる場面って想像つかないですが、ありましたらぜひ教えていただきたいです)

Helperオブジェクトへアクセスする

Helper クラスは基本的にViewから利用することを前提に設計されているため、それ以外の利用方法は非常に限定的です。実際の描画ロジックで使用されるインスタンスに事前にアクセスすることは(コアコードを編集しない限り)不可能な模様です。

Viewオブジェクト(テンプレートファイル含む)からHelperオブジェクトへアクセスする

Controller で設定した Helperオブジェクトへ自身のプロパティとしてアクセスできます。

サンプルコード(テンプレートからHtmlHelperオブジェクトへアクセスする)

<?php
echo $this->Html->link($label, $url);
?>

HelperオブジェクトからHelperオブジェクトへアクセスするには

Helperから別のHelperを参照するには自身のViewオブジェクトプロパティの $this->_View を経由してアクセスできます。直接プロパティを取得する方法と loadHelper メソッドを利用する方法とがあります。

// 直接 View のプロパティにアクセスする場合
$html = $this->_View->Html;
// View::loadHelper() を利用する場合
$html = $this->_View->loadHelper('Html');

Controller から Helperオブジェクトへアクセス出来るか?

Controller から Helperオブジェクトへアクセスする手段は特にありません。ビューで使用されるHelperのインスタンスはレンダリングの時点で生成されるため、通常はアクションメソッドやそれ以前のタイミングからは、(やがてレンダリングで用いられるところの)Helperのインスタンスにはアクセス出来ません。

ControllerからHelperを制御する方法は非常に限定されており、その恐らく唯一の方法はHelperのコンストラクタに引数を渡すことです。次のようにします。

サンプルコード(コントローラからHelperへ情報を渡す)

class AppController {
    public $helpers = array(
        'MyAppHelper' => array('config1' => 'value1', 'config2' => 'vlaue2'),
    );
}

あるいは

class PostsController {
    public function my_action() {
        $this->helpers['MyActionHelper'] = array('config1' => 'value1', 'config2' => 'vlaue2');
    }
}

render後のプロセスにおいてはControllerにセットされたViewのインスタンスを経由してHelperのインスタンスを取得できます。

サンプルコード(レンダリング完了後にHelperオブジェクトにアクセスできる。で、一体何をするの?さぁ・・・)

class PostsController {
    public function afterRender() {
        parent::afterRender();
        $htmlHelper = $this->View->loadHelper('Html');
    }
}

次のような方法では、ビューで使用されるものとは別のHelperインスタンスへのアクセスになります。(レンダリング時には別のインスタンスが新たに生成される)

// もしレンダリング時のヘルパーに何らかの操作をしたいと思っていたならこれは誤り
class PostsController {
    public function my_action() {
        // ビューで使用するヘルパーではない
        $htmlHelper = new View($this)->loadHelper('Html');
    }
}

Componentオブジェクトへアクセスする

Controller から Component オブジェクトへアクセスする

コントローラで $components として指定したコンポーネントへアクセスするには、自身のプロパティとして直接アクセスします。

class PostsController extends AppController {
    public $components = array('Security');
    public $whiteList = array('ajax');
    public function beforeFilter() {
        if (in_array($this->request->params['action'], $this->whiteList)) {
            // SecurityComponent に $this->Security としてアクセス
            $this->Security->validatePost = false;
        }
    }
}

それ以外の場合は ComponentCollection::load() を用います→ CakePHP2.0で、action内部からComponentを呼び出す方法

余談ですが、Model の名称と衝突した場合は Component が優先され、Model への参照は失われます。

Component オブジェクトへのこれ以外のアクセス方法は特に設定されていません。

CakeRequestオブジェクトへアクセスする

CakeRequest オブジェクトはクライアントのリクエストが CakePHP に最初に渡される webroot/index.php でインスタンス化され、その一つのインスタンスをプロセスの最後まで使いまわし、多くの場面で直接利用できます。まず自身のプロパティとしてセットされていないかを調べ、ない場合はセットされているインスタンスから取得するとよいでしょう。

CakeRequest へ自身のプロパティとしてアクセスできるクラス

どのオブジェクトに予めセットされているかはこちらのエントリをご覧ください。

CakeRequest/CakeResponse についてのメモ(自動的にメンバー変数としてアクセスできるクラス )

 

Controller のモックアップを作成する場合などは新たなCakeRequestオブジェクトが必要となる場合があります。そのような場合、任意に new してインスタンスを生成します。

CakeResponseオブジェクトへアクセスする

CakeResponseオブジェクトへアクセスするには上記の CakeRequestオブジェクトへのアクセス の説明とほぼ同等です。そちらをご覧ください。

CakeResponse へ自身のプロパティとしてアクセスできるクラス

どのオブジェクトに予めセットされているかはこちらのエントリをご覧ください。

CakeRequest/CakeResponse についてのメモ(自動的にメンバー変数としてアクセスできるクラス )

BehaviorCollectionオブジェクトへアクセスする

BehaviorCollectionオブジェクトへは Model::$Behaviors でアクセスします。

HelperCollectionオブジェクトへアクセスする

HelperCollectionオブジェクトへは View::$Helpers でアクセスします。

ComponentCollectionオブジェクトへアクセスする

ComponentCollectionオブジェクトへは Controller:$Components でアクセスします。

DATABASE_CONFIGオブジェクトへアクセスする

DATABASE_CONFIG オブジェクトへは ConnectionManager::$config で static にアクセスできます。

サンプルコード(拙作BackupbleプラグインのBasicBackup::_getTableName())

protected function _getTableName($model) {
    if ($model->tablePrefix) {
        $table = $model->tablePrefix . $model->useTable;
    } else {
        $table = ConnectionManager::$config->{$model->useDbConfig}['prefix'] . $model->useTable;
    }
    return $table;
}

DataSourceオブジェクトへアクセスする

Model で使用される DataSource オブジェクトへアクセスするには Model::getDataSource() を用います。

CakeRouteオブジェクトへアクセスする

Router クラス内でURL解決に使用されている CakeRouteオブジェクトは、Router::$routes の配列に格納されています。ここにセットされているオブジェクトへアクセスするには順次これをループさせて該当するオブジェクトを見出してください。

この配列は単純インクリメントされた数値添字でありマッピング情報も用意されていませんので、直接的に任意のオブジェクトを抜き出すことはできません。

サンプルコード[ TestSuite/ControllerTestCase::_testAction ]

// RedirectRoute (CakeRequest の継承クラス)オブジェクトをRouter::$routes をループさせて検索している
foreach (Router::$routes as $route) {
    if ($route instanceof RedirectRoute) {
        $route->response = $this->getMock('CakeResponse', array('send'));
    }
}

また、実際に解析に成功した CakeRoute オブジェクトは protected Router::$_currentRoute 配列にプッシュされており、これの先頭の要素を Router::currentRoute() で取得出来ます。通常は最初に一度だけリクエストURLを解析するだけなのでどちらの値も同じですが、任意のURL文字列をパースした場合など、その都度リファレンスが追加されていきます。この配列のそれ以外の要素へのアクセス方法は現時点では提供されていません。