9

getServiceLocator をいつ使用し、いつ使用しないかについて、私は本当に混乱しています。例として:

+ Module
-+ Helloworld
--+ src
---+ Controller
----+ IndexController.php
----+ IndexControllerFactory.php

---+ Service
----+ LogginService.php
----+ GreetingService.php
----+ GreetingServiceFactory.php

GreetingServiceFactory.php の内容は次のとおりです。

<?php
namespace Helloworld\Service;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;


class GreetingServiceFactory implements FactoryInterface
{

    public function createService (ServiceLocatorInterface $serviceLocator)
    {
        $greetingService = new GreetingService();

        $greetingService->setEventManager($serviceLocator->get('eventManager'));

        $loggingService = $serviceLocator->get('loggingService');

        $greetingService->getEventManager()->attach('getGreeting', array(
            $loggingService,
            'onGetGreeting'
        ));

        return $greetingService;
    }
}

また、IndexControllerFactory.php の内容は次のとおりです。

<?php
namespace Helloworld\Controller;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class IndexControllerFactory implements FactoryInterface
{

    public function createService (ServiceLocatorInterface $serviceLocator)
    {
        $ctr = new IndexController();

        $ctr->setGreetingService($serviceLocator->getServiceLocator()
            ->get('greetingService'));
        return $ctr;
    }
}

ご覧のとおり、ControllerFactory には $serviceLocator->getServiceLocator() が必要ですが、ServiceFactory には必要ありません。なんで?どちらも getServiceLocator() メソッドを定義していない同じインターフェイス ServiceLocatorInterface を使用します。

module.config.php:

'controllers' => array(
    'factories' => array(
        'Helloworld\Controller\Index' => 'Helloworld\Controller\IndexControllerFactory'
    )
)
,
'service_manager' => array(
    'invokables' => array(
        'loggingService' => 'Helloworld\Service\LoggingService'
    ),
    'factories' => array(
        'greetingService'=> 'Helloworld\Service\GreetingServiceFactory'
    ),
)

説明をいただければ幸いです:)

良い1日を!

4

4 に答える 4

20

メソッドは、を実装しているため、でgetServiceLocator定義されています。Maks3wが指摘したように、これはの一部ではないため、サービスファクトリを実装するときに使用しないでください。AbstractPluginManagerServiceLocatorAwareInterfaceServiceLocatorInterface

とにかく、ファクトリをクロージャとして定義し、それを使用することができます。

class MyModule
{
    public function getControllerConfig()
    {
        return array(
            'factories' => array(
                'IndexController' => function (
                    \Zend\ServiceManager\AbstractPluginManager $pm
                ) {
                    $ctr = new IndexController();

                    $ctr->setGreetingService(
                        $pm
                            ->getServiceLocator()
                            ->get('greetingService')
                    );

                    return $ctr;
                },
            ),
        );
    }
}

この例$pmは確かにServiceLocatorInterfaceインスタンスですが、にアクセスするには「メイン」サービスマネージャーへの参照を取得する必要があります'greetingService'

ZF2は、コントローラー、サービス、ビューヘルパー、コントローラープラグインなどに、さまざまなサービスマネージャーまたはプラグインマネージャーを使用します。これは、主にタイプヒント(AbstractPluginManagerタイプの厳密性がどのように達成されるかを理解するためにのインターフェイスを参照)とセキュリティのためです。

controllerこの場合、セキュリティの問題は、特に動的パラメータを持つルートで、コントローラではないサービスへのアクセスを許可しないことです。そのため、コントローラーは別のプラグインマネージャーに保持されます。

コントローラプラグインマネージャは「メイン」サービスマネージャから作成されるため、。のおかげで初期化されますServiceLocatorAwareInterface

これをより明確にするために、関係のグラフを追加しました(ファクトリは含まれず、有効なUMLとは見なされません)。

疑似UML

于 2013-02-16T21:11:09.243 に答える
5

ご覧のとおり、ControllerFactory には $serviceLocator->getServiceLocator() が必要ですが、ServiceFactory には必要ありません。なんで?

コントローラ ファクトリは、メインのサービス マネージャ インスタンスとは異なるサービス マネージャ インスタンス (「ControllerLoader」) によって呼び出されます。これは、ディスパッチャーがメイン サービス マネージャーによって任意のクラスをインスタンス化できないようにするためです。

その結果、コントローラー ファクトリの $serviceLocator は、「greetingService」がメイン サービス マネージャーに登録されているため、「greetingService」を取得するときに必要なものではありません。コントローラーからメイン サーバー マネージャーを取得するには、getServiceLocator() を使用します。これで、「グリーティング サービス」を get() できるメイン サービス マネージャーのインスタンスができました。

これは「ピアリング」として知られています。つまり、「ControllerLoader」サービス マネージャー (config の「controllers」キーまたはモジュール クラスの getControllerConfiguration() を介して構成されたもの) は、メイン サービス マネージャーをピアとして設定します。

于 2013-02-17T11:28:16.490 に答える
3

getServiceLocatorそのメソッドはServiceLocatorInterface代わりに使用するように定義されていないため、絶対に使用しないでくださいget()

于 2013-02-16T15:45:04.963 に答える