2

編集:この質問を投稿してから数週間後、Evan Coury が ZF2 ServiceManager のトピックに関する優れたブログ投稿を書きました。 -zend-framework-2-servicemanager

--

ZendFramework 2.0.0beta4 を使用するプロジェクトに取り組んでおり、Zend\ServiceManager を使用して依存関係を処理するのに問題があります。現在のZF2 ServiceManager のドキュメントは次のとおりです。

モジュールで使用するクラスを ServiceManager に登録するときに使用する 6 つのサブキーをリストします: abstract_factoriesaliasesfactoryinvokablesservices、およびshared。データベースからデータを取得するためにコントローラーで使用するモデル クラスを登録したいだけの場合、どれが最適ですか? 具体的には、以下に示すZF2 スケルトン アプリケーションの例を自分のアプリケーション (DashboardTable がモデル)に適合させようとしています。この例では、ファクトリの方法を使用しています。

public function getServiceConfiguration()
{
    return array(
        'factories' => array(
            'album-table' => function($sm) {
                $dbAdapter = $sm->get('db-adapter');
                $table = new DashboardTable($dbAdapter);
                return $table;
            },
            'test-model' => Dashboard\Model\TestModel(),
        ),
    );
}

ただし、「db-adapter」が、SkeletonApplication とは別の作業例で ServiceManager ($sm) にどのように取り込まれているかはわかりません。 DB 情報を含む db' エントリ。構成ファイルから ServiceManager にどのように到達するのか正確にはわからないため、その下に単純なエントリを作成して、問題をその基本コンポーネントである「test-model」に減らしました。「dashboard-table」エントリをコメントアウトし、コントローラーで TestModel から関数を呼び出すと、単純にテキストが出力されます。以下は、私の Module.php の ServiceManager 構成です。

<?php

namespace Dashboard\Model;

class TestModel {

public function testMethod()
{
    $testResult = "Hello";
    return $testResult;
}

}

次に、コントローラーからビューに渡されます。

<?php

namespace Dashboard\Controller;

use Zend\Mvc\Controller\ActionController;
use Zend\View\Model\ViewModel;
use Dashboard\Model\AlbumTable;
use Dashboard\Model\TestModel;
use Dashboard\Model\Dashboard;

class DashboardController extends ActionController
{
    public function indexAction()
    {   
        return new ViewModel(array(
            'users' => $this->getTestModel()->testMethod(),
        ));
    }

    public function getAlbumTable()
    {
        if (!$this->albumTable) {
            $sm = $this->getServiceLocator();
            $this->albumTable = $sm->get('album-table');
        }
        return $this->albumTable;
    }

    public function getTestModel()
    {
        if (!$this->testModel) {
            $sm = $this->getServiceLocator();
            $this->testModel = $sm->get('test-model');
        }
        return $this->testModel;
    }

}

このコードにより、エラーのない完全に空白のページが表示されます。Module.php から ServiceManager 構成をコメントアウトし、DashboardController.php ファイルに引数を渡さずに新しい ViewModel をレンダリングすると、ページは正常にレンダリングされます - layout.phtml と index.phtml をロードします。

ServiceManager または ZF2 の一般的な使用方法の基本的な部分を誤解していると思います。これは StackOverflow に関する私の最初の質問でもあるため、質問の書式設定に関するアドバイスを歓迎します。ありがとう。

4

3 に答える 3

3

サービス マネージャーからファクトリを取得するには、2 つの適切なオプションがあります。1 つはファクトリ クラスの作成で、ほとんどの場合、Zend Framework コード自体で行われます。2 つ目は、あなたが行っているように、クロージャを使用しています。

次のようなものは入力しないでください。

'test-model' => Dashboard\Model\TestModel(),

しかし、最初のクロージャーのような実際のクロージャーは良い例です。第 2 に、インスタンス化に失敗したサービスを取得しようとすると、Service Manager は常に例外を返します。この例外には、why というメッセージが含まれていないことに注意してください: クラスが見つからないか、インスタンス化中に例外がスローされます (たとえば、取得しようとしているサービスの依存関係をサービス マネージャーがインスタンス化できないため)。

最後の注意点は、取得useしようとしている場所のステートメントでFQCN (完全修飾クラス名) をインポートする必要がないことです。ただし、インスタンス化しようとしている場合は、FQCN をインポートする必要があります。

したがって、これは機能します:

<?php

class MyClass
{
  protected $sm;

  public function setServiceManager($sm)
  {
    $this->sm = $sm;
  }

  public function doSomething()
  {
    $this->sm->get('some-special-key');
  }
}

そしてこれも:

<?php

use Foo\Bar\Baz;

$serviceConfig = array(
  'factories' => array(
    'some-special-key' => function($sm) {
      return new Baz;
    }
  ),
);

しかし、これはそうではありません(を取得しようとした場合Foo\Bar\Baz):

<?php

$serviceConfig = array(
  'factories' => array(
    'some-special-key' => function($sm) {
      return new Baz;
    }
  ),
);

私のSlmCmfKernelリポジトリをチェックアウトすることをお勧めします。私のModule.phpには、別の場所にあるサービス構成ファイルが含まれています。コードの別の部分では、マネージャーからサービスを受けます。

于 2012-06-24T07:57:09.893 に答える
2

明確にするために:

public function getServiceConfiguration()
{
    return array(
        'factories' => array(
            'test-model' => function($sm){
                return new Model\TestModel;
            },
        ),
    );
}

呼び出し可能なものとして書くこともできます:

public function getServiceConfiguration()
{
    return array(
        'invokables' => array(
            'test-model' => 'Model\TestModel',
        ),
    );
}

その場合は、Module.php の代わりに構成ファイルで定義することを検討することをお勧めします。これは、単にスカラーの配列であるため、構成キャッシュを利用できるためです。

于 2012-07-21T01:14:11.380 に答える
1

私は、より多くのデバッグを通じて自分の質問に対する答えを見つけることになりました(以前は ini_set('display_errors', '1'); を設定していませんでした-ばかげています)。

ZF2 ServiceManager (Module.php 内) にクラスを追加する適切な構文は次のようになります。

public function getServiceConfiguration()
{
    return array(
        'factories' => array(
            'album-table' => function($sm) {
                $dbAdapter = $sm->get('db-adapter');
                $table = new AlbumTable($dbAdapter);
                return $table;
            },
            'test-model' => function($sm){
                return new Model\TestModel;
            },
        ),
    );
}

そして完全を期すために、含めているクラスからメソッドを呼び出すために、 ActionController クラスを拡張している限り、コントローラーファイル (私の場合はDashboardController.php) でこれを使用できます:

class DashboardController extends ActionController
{
    public function indexAction()
    {   
        return new ViewModel(array(
            'users' => $this->getTestModel()->testMethod(),
        ));
    }

    public function getTestModel()
    {
        if (!$this->testModel) {
            $sm = $this->getServiceLocator();
            $this->testModel = $sm->get('test-model');
        }
        return $this->testModel;
    }

}

testMethod() は TestModel クラス内のメソッドです。Zend や名前空間を初めて使用する人向けのメモです。私の問題の 1 つは、ファイルの先頭にある名前空間を Dashboard に設定したときに、完全なクラス名参照 (Dashboard\Model\TestModel) を使用していたことです。最初の Dashboard は不要で、PHP が Dashboard\Dashboard\Model\TestModel を探す原因になりました。また、この記事の執筆時点では、ZF2 モジュールのサンプルは不足しています。この種の例については、EvanDotPro による ZfcUser などのサンプルを参照することをお勧めします。

ただし、ServiceManager にクラスを追加するためのさまざまなサブキーに関する最初の混乱はまだ残っているため、それについての洞察があれば、この質問を引き続き監視し、そのビットを解決する必要がある場合は、回答を「その」回答としてマークします。 、 ありがとうございました :)。

于 2012-06-23T21:33:27.753 に答える