コンポーネント、ヘルパー、ビヘイビアそしてタスクは皆、似たような構造と一連の振る舞いを共有しています。 2.0では、同種のオブジェクトのコレクションとやり取りできる統一APIがそれらに与えられました。 CakePHPのこのコレクションオブジェクトは、アプリケーション内の様々な異なる種類のオブジェクトとのやり取りにおいて統一された方法を提供します。
以下においてはコンポーネントを例に用いることになりますが、同じ振舞いはコンポーネントの他にもヘルパー、ビヘイビア、そしてタスクに期待出来ます。
すべての種類のコレクションにおいて、オブジェクトのロードは load() メソッドを使えば可能になります:
$this->Prg = $this->Components->load('Prg');
$this->Prg->process();
あるコンポーネントをロードする時点において、そのコンポーネントがコレクションにロードされていないなら新しいインスタンスが生成されます。 もし既にそのコンポーネントがロードされているなら、別のインスタンスは新たに生成されません。 ロードする際に、コンポーネントに設定を追加することもできます:
$this->Cookie = $this->Components->load('Cookie', array('name' => 'sweet'));
設定を追加したどんなキーも値もコンポーネントのコンストラクタに渡されることになるでしょう。 このルールの一つの例外は className です。 className は、コレクションにおけるオブジェクトのエイリアスとして用いられる特別なキーです。 これにより、クラス名を反映させないコンポーネント名(コアのコンポーネントを拡張する際に便利です)を使えるようになります:
$this->Auth = $this->Components->load('Auth', array('className' => 'MyCustomAuth'));
$this->Auth->user(); // 実際には MyCustomAuth::user() が使用されます
オブジェクトのロードの逆を行うこと、それがアンロードするということです。 アンロードされたオブジェクトはメモリから消去され、それによりトリガーされるコールバックを追加されることもありません:
$this->Components->unload('Cookie');
$this->Cookie->read(); // Fatal error.
コレクションオブジェクトはコールバックをサポートします。 トリガーされたコールバックをコレクションが持っていると、そのメソッドはコレクション内の実行可能(enabled)なすべてのオブジェクトに対してコールされます。 さらに、パラメータをコールバックのループに渡すことも出来ます:
$this->Behaviors->trigger('afterFind', array($this, $results, $primary));
上の例において $this は全てのビヘイビアの afterFind メソッドに第一引数として渡されます。 コールバックの起動の仕方を制御できる様々なオプションがあります:
break や breakOn オプションを用いることで、コールバックループを JavaScript におけるイベント伝播を停止させるような感じで途中でキャンセルすることができます:
$this->Behaviors->trigger(
'beforeFind',
array($this, $query),
array('break' => true, 'breakOn' => false)
);
上の例では、全てのビヘイビアが beforeFind メソッドから false を返すなら、それ以上コールバックが呼ばれることはありません。 ちなみに、 trigger() の戻り値は false になるはずです。
一度コレクションにロードしたオブジェクトを無効化したくなることがあるかもしれません。 コレクション内のオブジェクトを無効化することで、それ以降、 triggerDisabled オプションを用いない場合のコールバックの発火を防ぎます:
// HtmlHelper を無効化
$this->Helpers->disable('Html');
// その後、そのヘルパーを再有効化
$this->Helpers->enable('Html');
無効化されたオブジェクトはまだそれらの通常のメソッドとプロパティを持っています。 有効状態と無効状態の根本的な違いはコールバックに関してです。 enabled() メソッドを用いることで、有効オブジェクトに何があるのかを問い合わせたり、特定のオブジェクトがまだ有効であるのかをチェックすることが出来ます:
// あるヘルパーが有効かどうかをチェックします
$this->Helpers->enabled('Html');
// $enabled はこの時点で有効なヘルパーの配列です
$enabled = $this->Helpers->enabled();
イベントコールバックに対して行うのと同じように、オブジェクトコールバックをトリガーする順番を指定することが出来ます。 プライオリティ値とトリガーの順番との取り扱いは ここ の説明と同じです。 宣言時にプライオリティを設定できる方法は次に示します:
class SomeController {
public $components = array(
'Foo', //Foo はデフォルトのプライオリティ 10 を持ちます
'Bar' => array('priority' => 9) //Bar のコールバックは Foo's の前にトリガーされます
);
public $helpers = array(
'Cache' => array('priority' => 12), //Cache のコールバックは最後に
//トリガーされるでしょう
'Asset',
'Utility' //Utility は Asset と同じプライオリティ 10 を持ち、そのコールバックは
//Asset のものよりあとにトリガーされます
);
}
class Post {
public $actsAs = array(
'DoFirst' => array('priority' => 1),
'Media'
);
}
コレクションへ動的にオブジェクトをロードした場合、こんな感じで優先順位を指定出来ます:
$this->MyComponent = $this->Components->load('MyComponent', array('priority' => 9));
ObjectCollection::setPriority() メソッドを用いることで、 実行途中に優先順位を変更することも出来ます:
//オブジェクトがひとつの場合
$this->Components->setPriority('Foo', 2);
//オブジェクトが複数の場合
$this->Behaviors->setPriority(array('Object1' => 8, 'Object2' => 9));