1

以下のコードを使用して、ブートストラップ クラスを使用してモジュールをフロント コントローラーに登録しようとしています。

$this->bootstrap('FrontController');
$front = $this->getResource('FrontController');     
$front->addModuleDirectory(APPLICATION_PATH."/modules");
$front->setParam('prefixDefaultModule', true);

これは正常に機能し、すべてのモジュールが登録されています。しかし、次のようにすると、モジュール ディレクトリが登録されず、「コントローラーが見つかりません」というエラーが表示されます。

$front = Zend_Controller_Front::getInstance();
$front->addModuleDirectory(APPLICATION_PATH."/modules");
$front->setParam('prefixDefaultModule', true);

フロント コントローラーはシングルトン デザイン パターンを実装するので、両方のコード ブロックが同じインスタンスを参照し、両方のコード ブロックが機能するはずではありませんか?

4

3 に答える 3

3

問題は、application.ini の次の行です。

resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"

あなたが与えたファイル構造にはこのディレクトリが含まれていないので、削除して問題を解決できると思います。

なぜそれが一方の方法で機能し、他方の方法では機能しないのかについてのより長い説明:

Zend アプリケーションでリソースを構成するには、クラスリソースとプラグインリソースの 2 つの方法があります。application.iniのresources.xxx行はプラグイン リソースで、_initメソッドはクラス リソースです。クラス リソースはプラグイン リソースの前に実行されますが、実行$this->bootstrap('...')すると、(タイプに関係なく) リソースが確実に初期化されます。

したがって、最初のコード例で$this->bootstrap('FrontController');は、application.ini で定義した frontController リソースをトリガーします。次に、指定したパスを使用してコントローラ ディレクトリを設定します。次に、アプリケーションが実際に使用していると思われるモジュール ディレクトリを追加します。

2 番目のコード例では、フロント コントローラーのインスタンスを取得し、それにモジュール ディレクトリを追加します (すべて問題ありません)。しかしその後、プラグインリソースが実行されます (後で実行されることを思い出してください)。これにより、既存のフロントコントローラーインスタンスが取得されますが、コントローラーディレクトリを設定するとモジュールディレクトリが上書きされるため、後でエラーが発生します.

私は通常、プラグインとクラスのリソースを混在させたり一致させたりしないようにしています。奇妙な問題が発生する可能性があるからです。したがって、すべてを application.ini に入れるか、すべてを Bootstrap クラスに入れます。個人的には後者の方が読みやすいと思います。

コントローラー ディレクトリも必要な場合は$this->bootstrap('FrontController');、2 番目のコード例の先頭に追加しても、プラグイン リソースがトリガーされるため、同様に機能するはずです。

于 2013-06-22T21:00:09.767 に答える
1

これが何が起こっているかです。ティム・ファウンテンは正しいです。application.ini ファイルの次の行が原因です。これを削除すると、アプリケーションが正しく読み込まれるはずです。

resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"

この行もフロントコントローラーの一部であるため、削除する必要がある場合があります。

resources.frontController.params.displayExceptions = 1 

ただし、使用できる他の2つのオプションもありますZend_Controller_Front::getInstance()

オプション 1. index.php を変更して、特定のリソースをブートストラップします。

$application->bootstrap(array('FrontController', 'ModuleConfig'))->run();

これにより、まず application.ini から FrontController がブートストラップされ、次にinitModuleConfigメソッドが実行されます。基本的に、これにより、どのリソースをどの順序でロードするかを制御できます。これは、特定の時間にのみブートストラップしたいリソースがある場合に役立ちます。

initここでブートストラップ メソッドに配列を指定しないと、宣言された順序で接頭辞が付いたすべてのメソッドが呼び出されると思います。

オプション 2. application.ini 内でモジュール ディレクトリの構成を行うことができます。

resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.params.prefixDefaultModule = 1
resources.frontController.params.displayExceptions = 1 

これにより、コードで実行しようとしていたことが実行されます。Bootstrap注意すべきことの 1 つは、クラスのコンストラクターで FrontController をブートストラップしたい場合があることです。これは、カスタムの初期化中に使用する必要がある場合に備えてのものです。


ここで、オプション 1 が機能する理由について説明します。

からのメソッドです。Zend_Application_Bootstrap_BootstrapAbstract

protected function _bootstrap($resource = null)
{
    if (null === $resource) {
        foreach ($this->getClassResourceNames() as $resource) {
            $this->_executeResource($resource);
        }

        foreach ($this->getPluginResourceNames() as $resource) {
            $this->_executeResource($resource);
        }
    } elseif (is_string($resource)) {
        $this->_executeResource($resource);
    } elseif (is_array($resource)) {
        foreach ($resource as $r) {
            $this->_executeResource($r);
        }
    } else {
        throw new Zend_Application_Bootstrap_Exception('Invalid argument passed to ' . __METHOD__);
    }
}

これは、パブリックメソッド_bootstrapを呼び出すときに呼び出されます。bootstrap$this->bootstrap("FrontController")または$this->bootstrap();

パラメータを渡さない場合に注意してください。nullこれは、あなたがあなたに得るケースであるケースを呼び出しますindex.php-$application->bootstrap()->run();

最初にあなたをロードしclass resources、次にあなたのplugin resources. plugin resourcesその他の場合はロードされないことに注意してください。

クラスリソースのメソッド呼び出しに従う場合、基本的にはinitブートストラップ呼び出しクラスでメソッドを呼び出します。

プラグイン リソースは後で呼び出され、プラグイン リソースの 1 つです。すべてのプラグイン リソースがどのように読み込まれるかは完全にはわかりませんが、1 つのソースがあなたのapplication.iniファイルにあると思います。これらは で始まる行になりますresources。例には、views、frontcontroller、db が含まれます。

したがって、 を呼び出す状況では$application->bootstrap()->run();initメソッドが最初にロードされます。しかし、あなたFrontControllerはまだブートストラップされていません。最終的には、application.ini. これは明らかに、ブートストラップ クラスで行ったことを上書きします。

もう 1 つの質問として、$this->bootstrap("FrontController)明示的に呼び出したときに FrontController インスタンスがオーバーライドされない理由があります。これはかなり明白だと思いますが、個人的には私自身がこの質問をしました。

Bootstrap クラスには、呼び出されるメソッドがあり_executeResource、リソースが既にブートストラップされているかどうかを確認します。連想配列を使用して追跡します。連想配列は と呼ばれ$this->_startedます。

これが、フロント コントローラーを明示的にブートストラップする最初のケースで、フロント コントローラーのプラグイン リソースが呼び出されない理由です。したがって、フロント コントローラー インスタンスは置き換えられません。

于 2013-06-22T07:35:05.203 に答える
0

最初にフロントコントローラーをブートストラップして、初期化する必要があります。サイクルで完了したら、静的な getInstance でいつでも取得できます。

于 2013-06-22T05:48:35.140 に答える