10 月 10
[symfony]Class ‘BaseFormPropel’ not foundエラー解決
以前、[symfony]Fatal error: Class 'BaseFormPropel' not foundというsymfony 1.1でフォームとPropelを組み合わせたときのエラーについて書いたことがあります。その時は解決には至らず、適当な回避策でごまかしていましたが、やはり開発に影響が出たので詳しく調べて、原因を突き止め、(たぶん)解決まで至りました。
どうやら、一定の条件を満たしているときに発生することがわかりました。
発生条件
以下のすべてを満たしているとき、「Class 'BaseFormPropel' not found」エラーが発生すると思われます。
- symfony 1.1(普通)
- O/RマッパーはPropel(普通)
- symfony propel:build-formコマンドなどで作った、Propelと連携したフォームクラスがある(普通)
- autoload.ymlを拡張していない(普通)
- symfony本体を/libディレクトリの中に保持している
- /libディレクトリの中に保持しているsymfony本体のディレクトリ名が"symfony"以外(ex: symfony-1.1.x)
「Class 'BaseFormPropel' not found」エラー内容のおさらい
Propelと連携したフォームクラスを用いると、以下のようなエラーが表示され、スクリプトが中断します。
-
[?php /** * Project form base class. * * @package form * @version SVN: $Id: sfPropelFormBaseTemplate.php 6174 2007-11-27 06:22:40Z fabien $ */
-
abstract class BaseFormPropel extends sfFormPropel { public function setup() { } }
-
Fatal error: Class 'BaseFormPropel' not found in /path-to-project/lib/form/base/BaseMemberForm.class.php on line 10
調査
- 画面に表示された内容は以下のファイル内容そのまま
TEXT:
-
/path-to-project/lib/symfony-1.1.x/lib/plugins/sfPropelPlugin/data/generator/sfPropelForm/default/template/sfPropelFormBaseTemplate.php
-
- キャッシュとして生成されたconfig_autoload.yml.phpの内容からBaseFormPropelに関する内容を抜き出すと以下のようになる
php:
-
// auto-generated by sfAutoloadConfigHandler
-
// date: 2008/10/09 16:56:11
-
// project
-
'BaseFormPropel' => '/path-to-project/lib/form/BaseFormPropel.class.php',
-
'BaseFormPropel' => '/path-to-project/lib/symfony-1.1.x/lib/plugins/sfPropelPlugin/test/functional/fixtures/lib/form/BaseFormPropel.class.php',
-
'BaseFormPropel' => '/path-to-project/lib/symfony-1.1.x/lib/plugins/sfPropelPlugin/data/generator/sfPropelForm/default/template/sfPropelFormBaseTemplate.php',
-
);
-
- 上記から読み取れることは、autoload.ymlのprojectというルールにおいて、BaseFormPropelの定義が複数ある。一番最後に上書きした定義はエラーとして画面に表示されたファイルを指している
- つまり、autoload.ymlのprojectルールがよくない。
原因
デフォルトのautoload.ymlは$sf_symfony_lib_dir/config/autoload.ymlにあります。このうち、projectルールだけを取り出すと以下のようになっています。
-
autoload:
-
# プロジェクト
-
project:
-
name: project
-
path: %SF_LIB_DIR%
-
recursive: on
-
exclude: [model, symfony]
日本語で書けば、projectという名前のルールは、%SF_LIB_DIR%(/path-to-project/lib)を基準に再帰的にクラスを検索するが、modelとsymfonyという名前のディレクトリは除外するルールのようです。おそらく、/path-to-project/libにsymfony本体を置く場合、ディレクトリ名をsymfonyとする習慣があるので、それを考慮して除外ルールが設定されているのではないでしょうか。そして、今回はsymfony-1.1.xというディレクトリ名でsymfony本体を置いてしまいました。当然除外ルールには該当しないので、symfony本体に含まれる大量のクラスがautoload対象になってしまったのです。
解決策
1つは、/path-to-project/libに置いたsymfony本体のディレクトリ名をsymfonyに変更することです。おそらくこれが一番シンプルな解決策です。前述した除外ルールも適用されるはずです。
もう1つは、各アプリケーションにautoload.ymlを設置し、projectルールを上書きして、除外ディレクトリ名にsymfony-1.1.xなどのsymfony本体のディレクトリ名を追加することです。何らかの理由によってsymfony本体のディレクトリを変更できない場合はこの方法が有効です。
たぶんこれで解決したのではないでしょうか。
それにしてもsymfonyって設定に慣れないと面倒ですね。。。

