10

[symfony]Class ‘BaseFormPropel’ not foundエラー解決

Tag: phpuechoco @ 18 : 20 : 54

以前、[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:
  1. [?php /** * Project form base class. * * @package form * @version SVN: $Id: sfPropelFormBaseTemplate.php 6174 2007-11-27 06:22:40Z fabien $ */
  2. abstract class BaseFormPropel extends sfFormPropel { public function setup() { } }
  3. Fatal error: Class 'BaseFormPropel' not found in /path-to-project/lib/form/base/BaseMemberForm.class.php on line 10

調査

  • 画面に表示された内容は以下のファイル内容そのまま
    TEXT:
    1. /path-to-project/lib/symfony-1.1.x/lib/plugins/sfPropelPlugin/data/generator/sfPropelForm/default/template/sfPropelFormBaseTemplate.php

  • キャッシュとして生成されたconfig_autoload.yml.phpの内容からBaseFormPropelに関する内容を抜き出すと以下のようになる
    php:
    1. // auto-generated by sfAutoloadConfigHandler
    2. // date: 2008/10/09 16:56:11
    3. return array(
    4. // project
    5. 'BaseFormPropel' => '/path-to-project/lib/form/BaseFormPropel.class.php',
    6. 'BaseFormPropel' => '/path-to-project/lib/symfony-1.1.x/lib/plugins/sfPropelPlugin/test/functional/fixtures/lib/form/BaseFormPropel.class.php',
    7. 'BaseFormPropel' => '/path-to-project/lib/symfony-1.1.x/lib/plugins/sfPropelPlugin/data/generator/sfPropelForm/default/template/sfPropelFormBaseTemplate.php',
    8. );

  • 上記から読み取れることは、autoload.ymlのprojectというルールにおいて、BaseFormPropelの定義が複数ある。一番最後に上書きした定義はエラーとして画面に表示されたファイルを指している
  • つまり、autoload.ymlのprojectルールがよくない。

原因

デフォルトのautoload.ymlは$sf_symfony_lib_dir/config/autoload.ymlにあります。このうち、projectルールだけを取り出すと以下のようになっています。

php:
  1. autoload:
  2.   # プロジェクト
  3.   project:
  4.     name:           project
  5.     path:           %SF_LIB_DIR%
  6.     recursive:      on
  7.     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って設定に慣れないと面倒ですね。。。

Leave a Reply