Zend_ApplicationとZend_Loader_Autoloader、suppressNotFoundWarningsで困った(けど、原因がわかりました 追記)

ZF1.8RCでそれぞれテストして良好だったんですが、それで余裕ぶっこいて1.8.0の正規リリースをいきなり投入したら困ったことになりました。
原因箇所はほぼ特定できたんですが、技術的な要因がサッパリわかりません。うーん。

現象

Zend_ApplicationとZend_Loader_Autoloaderを同時に使い、Zend_Applicationのコンストラクトオプションで

<?php
    $application = new Zend_Application(
        $env,
        array(
            'autoloadernamespaces' => array('Zend_', 'Flower_'),
            'bootstrap' => FL_PATH_SYSTEM . '/Bootstrap.php',
            'resources' => array(
                 'modules' => array(),
            ),
        )
    );

としたとき、ハングアップするというもの。
環境はWindows Vista Ultimate SP1 上のZend Server CEです。
無限ループしているのか、なんなのか、ログも残らないので痛いです。

問題個所

ハングアップする箇所は、Zend_Loader::loadClass中の83行目付近、include $file;です。$fileはmodules.phpです。
Zend_Applicationのインスタンス化前後でclass_existsやautoload、もしくは直接includeするときには、問題が発生しないのですが、Zend_Applicationからだとハングアップします。(謎
ZF1.7ベースのZend_Loaderでも、問題ないんですが・・・
で、多分、こういう問題は環境とも関係があって、再現性に乏しいんじゃないかと。痛いですね。

ハングアップするフローを確認

modulesというキー名に対応するプラグインリソースをロード可能かチェックする際に、Zend_Application_Bootstrap_Bootstrap::registerPluginResourceでは、modulesという名前に対して、class_existsを第2引数なしでコールしています。class_existsの第2引数が省略されると、autoloaderが走って、クラスのロードを試みます。この機能は、コンストラクトオプションでクラス名が指定されたときに、自動的にロードして処理するためのものです。
ところが、このとき、modulesというキー名はプラグインリソースのショートカット名であって、クラス名ではないので、存在しないファイルをインクルードしに行っているので、suppressNotFoundWarningsがfalseならwarningが出ます。
そもそもそこで、autoloadはしてほしくないんですが、それについては、
Issue - Zend Framework
こちらでissueが上がっています。
suppressNotFoundWarningsがtrueの場合、ここでwarningが出ず、プロセスが逝ってしまいます。ちなみに、modulesでなくても、発生します。

suppressNotFoundWarningsのデフォルトはtrueになっている

これについては、ZF-6536で、falseをデフォルトにする方向で1.8.1のtodoに組み込まれるようです。
Issue - Zend Framework
でも、falseにすると、プラグインリソースにFrontControllerを含めていない場合はwarningが出るんですが、これはリソース指定を必須にする前提で進めるんでしょうか・・・

お手上げです

この問題、非常に痛いんですが、個別のテストでは問題が生じないことなので、解決しようとするとハマりそうです。1.8.1のリリースを待とうかと思ってます。
※自動アップデートとか怖すぎて使えないよ < Zend Server & Zend Framework

無限ループした原因(追記)

I think it's because of this change: (Zend/Application/Module/Bootstrap.php)

Index: Bootstrap.php
===================================================================

      • Bootstrap.php (revision 15357)
      1. Bootstrap.php (revision 15356)

@@ -51,7 +51,7 @@
*/
public function __construct($application)
{

  • parent::__construct($application);
  1. $this->setApplication($application);

$key = strtolower($this->getModuleName());
if ($application->hasOption($key)) {


I can't get PDT's debugger to work, but my guess is that the modules plugin pulls all the options from the application bootstrap including the resources. Since the module bootstrap is a child class of BootstrapAbstract, during bootstrap() it executes all the plugins again including the modules plugin, which runs all the module bootstraps again, which inherits and executes all plugins again, and so on.

-- Mon

http://www.nabble.com/Adding-Zend_Application_Module_Bootstrap-file-causes-application-to-fail-td23457724.html

こちらのログにあるのと同じ現象が起きていました。
モジュール別のブートストラップに対して、http://framework.zend.com/issues/browse/ZF-6545 で親クラスを呼ぶように変更されたのですが、この状態だと、親クラスで再度、モジュールブートストラップを読んで・・・という形で延々と新規オブジェクトが作られていくと言う・・・
でもこれ、簡単に解決できないんじゃない?

追記 stableじゃなかったようで

revを確認したのですが、1.8.0のstableではなく、trunkから持ってきていたようです。着手していただいているようなので、1.8.1リリースの頃には問題なくなっているはずです。

先ほどリリースされた1.8.1で解決されました。

いくつか似たissueが上がっていたようですが、主に、http://framework.zend.com/issues/browse/ZF-6545 に集約されています。
関連で、http://framework.zend.com/issues/browse/ZF-6591 こちらにもあります。