読者です 読者をやめる 読者になる 読者になる

CakePHPのmodel.phpをオーバーライドしたらFatal Error

PHP

最近CakePHPを使い始めたんだが、いきなりハマったのでその詳細を書いておく。

再現手順

  • 環境:PHP5.3.5+CakePHP1.3.6
  • CakePHPでは、すべてのモデルクラスの共通処理をapp/app_model.phpに書くのが流儀である。
  • というわけで、app_model.phpを以下のように書いてみる
class AppModel extends Model{
   function __construct() {
        parent::__construct();
        //なにか処理
    }
}
  • 次に、次のようなモデルを定義する。hasManyでBlogモデル同士で親子関係をもたせている。
class Blog extends AppModel {
    var $hasMany = array(
        'Parent' => array(
            'className' => 'Blog',
            'foreignKey' => 'parent_id',
        ),
    );
}
  • 最後にwebブラウザで適当なコントローラにアクセスすると・・・・
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 523800 bytes) in /xxx/cake/libs/debugger.php on line 94
  • Fatal errorで落ちます

何が駄目だったのか

  • AppModelのコンストラクタ引数が空だったのが問題
  • Modelクラスのコンストラクタ内でClassRegistry::addObjectしてるのだがコンストラクタを上書きして隠してしまっているので、いつまでたってもClassRegistryにクラスが登録されず、hasManyの解釈時に「Blogクラスがいないよー、Blogクラスがいないよー、・・・」といつまでも騒ぎ続けて、そのうちメモリがいっぱいになるのであった。
  • コンストラクタをオーバーライドしたいのなら以下のようにすべし
class AppModel extends Model{
   function __construct($id, $table, $ds) {
        parent::__construct($id, $table, $ds);
        //なにか処理
    }
}

結論

  • フレームワークのクラスをオーバーライドしたいときは、とりあえず対象のコードに目を通しておこう
  • エラーが発生するのはいいんですけど、このエラーメッセージから原因を特定するのは難しい
  • てかCodeZineで紹介されているこの記事(http://codezine.jp/article/detail/670?p=2)のサンプルコードはダメなんじゃないか
  • CakePHP触ってまだ1週間くらいなんで間違っている点があれば教えてください