2016-12-06 5 views
3

私のコントローラでは、サービスから、私はDBからウィジェットの名前のリスト(例えば、チャート、カレンダーなど)を取得します。すべてのウィジェットはWidgetInterfaceを実装しており、独自の依存関係として他のサービスが必要な場合があります。ウィジェットのリストはユーザーごとに異なる場合がありますので、私のコントローラーで必要なウィジェット/依存関係はわかりません。一般に、私は工場を使ってDIを介して依存関係を置いていますが、この場合コントローラの初期化時の依存関係はわかりません。 サービスロケータをコントローラで直接使用することは避けたい。その問題をどのように管理できますか?コントローラ工場でウィジェットの名前の一覧を取得する必要がありますか?そして、ウィジェットリストに依存して、すべての依存関係を取得し、それらをコントローラーに入れますか?私はKwidoとスヴェン・ビュイを示唆したように、私の問題を解決しZF2、開始時にわからない依存関係

おかげで、トム

ソリューション

は、それは意味、私は自分のプラグインマネージャーを構築しました。

利点:私はコントローラで直接サービスロケータを使用する必要はなく、さまざまな種類のウィジェットを取得するための明確で拡張可能な方法があります。

ありがとうございます。

答えて

1

ウィジェットのための何らかの種類のServiceManagerのような独自のマネージャを作成します。

class WidgetManager extends AbstractPluginManager 

Samsonik tutorial - pluginManagerをご覧ください。こうすることで、WidgetManagerを挿入して、このマネージャのウィジェットを関数として取得することができます。validatePluginは、フェッチされたインスタンスがWidgetInterfaceを使用しているかどうかをチェックします。親ServiceManagerを呼び出すことができることに注意してください。

また、ウィジェットの名前をサービスにマッピングするコントローラ用のプラグインを作成してください。このプラグインは、ファクトリまたはinvokableFactoriesによって作成されたかどうかにかかわらず、serviceLocator/Managerを使用してウィジェットを取得できます。したがって、ウィジェットを直接注入するのではなく、要求されたときにウィジェットを取得するだけです。本当に単純な何か:あなたのウィジェットのリストは時間があなたの要求を処理するためになりますので、成長するときのように何か他のものを、考慮するかもしれないので

protected $map = [ 
    // Widget name within the plugin => Name or class to call from the serviceManager 
    'Charts' => Widget\Charts::class, 
]; 

public function load($name) 
{ 
    if (array_key_exists($name, $this->map)) { 
     return $this->getServiceManager()->get($this->map[$name]); 
    } 

    return null; 
} 

すべてのウィジェットを注入するには、あなたのパフォーマンスのために悪いかもしれません。

これはあなたを助け、ある方向にあなたを押し込んだことを願っています。

1

これは実際に興味深い質問です。ウィジェットにはプラグインを使用することを検討することができます。プラグインはオンザフライでロードできます。

腐敗注射は良い習慣ですが、時には動的コンテンツでは実現できません。

これを行う別の方法は、独自のウィジェットマネージャを作成することです。このマネージャは、必要な特定のウィジェットを読み込むことができます。ウィジェットマネージャーをコントローラーに組み込むことができます。

編集: 上記のとおり、@kwidoと同じ考えです。

1

私は別のサービスを使用し、それをコントローラに注入します。

interface UserWidgetServiceInterface 
{ 
    public function __construct(array $widgets); 
    public function getWidget($name); 
} 

そしてコントローラ工場

class MyControllerFactory 
{ 
    public function __invoke(ControllerManager $controllerManager, $name, $requestedName) 
    { 
     $serviceLocator = $controllerManager->getServiceLocator(); 

     $userWidgetService = $serviceLocator->get('UserWidgetService'); 

     return new MyController($userWidgetService); 
    } 
} 

ウィジェットをロードするためのロジックはUserWidgetServiceFactoryに移動されるであろう。

public function UserWidgetServiceFactory 
{ 
    public function __invoke(ServiceManager $serviceLocator, $name, $requestedName) 
    { 
     $userId = 123; // Load from somewhere e.g session, auth service. 

     $widgetNames = $this->getWidgetNames($serviceLocator, $userId); 
     $widgets = $this->loadWidgets($serviceManager, $widgetNames); 

     return new UserWidgetService($widgets); 
    } 

    public function getWidgetNames(ServiceManager $sm, $userId) 
    { 
     return ['foo','bar']; 
    } 

    public function loadWidgets(serviceManager $sm, array $widgets) 
    { 
     $w = []; 
     foreach($widgets as $widgetName) { 
      $w[$widgetName] = $sm->get($widgetName); 
     } 
     return $w; 
    } 
} 

loadWidgets()を呼び出すと、すべてのウィジェットが読み込まれます。これを最適化したい場合は、ウィジェットを登録することができます。LazyServices

関連する問題