App::import と ClassRegistry::init の違い

命名規則に従わないモデルやプラグインをロードする際、使われるのが「App::import」と「ClassRegistry::init」。どういう使い分けをしているのかわからず、使い方によっては期待通り動かなかったりで困っていたので、違いを調べて見ました。

App::import

API Book によると、下記のような説明があります。

Finds classes based on $name or specific file(s) to search. Calling App::import() will not construct any classes contained in the files. It will only find and require() the file.

「コンストラクトは行わない。ファイルを探してrequire()するだけ」と書いています。

また、戻り値は

boolean true if Class is already in memory or if file is found and loaded, false if not

となっています。

結局このメソッドは「高機能なrequire」と考えて良さそうです。

ClassRegistry::init

これもAPI Bookを参考にすると、以下のように書かれています。

Loads a class, registers the object in the registry and returns instance of the object. ClassRegistry::init() is used as a factory for models, and handle correct injecting of settings, that assist in testing.

Return: object instance of ClassName

App::importと異なり、「オブジェクトのインスタンスを作成する」と書いています。

なるほど、テストケースの開始時に ClassRegistry::init() を、終了時に ClassRegistry::flush を行なうのも納得がいきます。テスト毎にモデルのインスタンスを初期化→削除しているんですね。

使い分け

  • 動的にモデルのインスタンスを使う時は ClassRegistry::init
  • それ以外は App::import

という使い分けで良さそうですです。

また検証していないのですが、「CakePHP モデルの読み込みは App::import ではなく ClassRegistry::init で - foldrrの日記」によると、App::importを使うとDBの接続先が $default 固定になってしまうため、ユニットテストで問題が出るそうです。

参考