2016-06-30 11 views
1

Ich bin neu in der modernen Methode der Abhängigkeitsinjektion und ich versuche herauszufinden, wie Sie eine Methode auswählen, welche Klasse basierend auf einer Bedingung zu verwenden. Ich wette, ich habe meine Design-Struktur deaktiviert, aber ich sehe auch nicht, wie man das in Aura DI über die Config macht.AuraPHP DI dynamische Klasse oder entscheidungsbasierte Injektion

Das ist meine Aura Config

<?php 
namespace Aura\Cli_Project\_Config; 

use Aura\Di\Config; 
use Aura\Di\Container; 

class Common extends Config { 
    public function define(Container $di) { 
     // utilities 
     $di->set(
      'App\Inventory\Utilities\EmailParser', 
      $di->newInstance('App\Inventory\Utilities\PlancakeParser') 
     ); 

     // commands 
     $di->params['App\Inventory\Command\IncomingOrder'] = array(
      'stdio' => $di->lazyGet('aura/cli-kernel:stdio'), 
      'parser' => $di->get('App\Inventory\Utilities\EmailParser') 
     ); 
    } 
    // ... 
} 

Und das ist die Klasse in Frage, die verschiedenen Klassen in Abhängigkeit von der „Quelle“ verwenden, muss es findet.

<?php 

namespace App\Inventory\Command; 

use Aura\Cli\Stdio; 
use App\Inventory\Utilities\EmailParser; 
use App\Inventory\Sources\Etsy; 
use App\Inventory\Sources\Amazon; 
use App\Inventory\Sources\Ebay; 

class IncomingOrder { 

    public function __construct(
     Stdio $stdio, 
     EmailParser $parser) { 
     $this->stdio = $stdio; 
     $this->parser = $parser; 
    } 

    public function process() { 
     // other code to parse message 
     // source is set by determining where it came from 
     $source = 'Etsy'; 

     switch($source) { 
      case 'Etsy' : 
       // This bit seems really wrong 
       $sourceParser = new Etsy\OrderParser(); 
       break; 
      case 'Amazon' : 
       $sourceParser = new Amazon\OrderParser(); 
       break; 
      case 'Ebay' : 
       $sourceParser = new Ebay\OrderParser(); 
       break; 
      default : 
       $sourceParser = null; 
     } 

     // Do source specific processing 
    } 
} 

Ist es, die ich brauche meine Verarbeitung an dem Punkt Recht zu spalten, nachdem die Quelle kann so eine neue Klasse bestimmt wird als Parameter mit dieser Quelle initialisiert werden?

Die einzige Möglichkeit, dies in der Konfiguration zu sehen, ist eine faule anonyme Funktion zu tun, um die richtige Quellklasse zurückzugeben, aber das fühlt sich auch gegen moderne Design-Prinzipien.

Antwort

2

Etwas, was ich gerne klarstellen möchte ist, dass Sie nicht set Methode wie viele der Di-Container hier verwenden müssen. Sie können den Code zu

<?php 
namespace Aura\Cli_Project\_Config; 

use Aura\Di\Config; 
use Aura\Di\Container; 

class Common extends Config 
{ 
    public function define(Container $di) 
    { 
     // commands 
     $di->params['App\Inventory\Command\IncomingOrder'] = array(
      'stdio' => $di->lazyGet('aura/cli-kernel:stdio'), 
      'parser' => $di->lazyNew('App\Inventory\Utilities\EmailParser') 
     ); 
    } 
    // ... 
} 

ändern Sie können von set, wenn Sie das gleiche Objekt viele andere Objekte übergeben wollen. Verwenden Sie nicht newInstance, denn es wird das Objekt beim Aufruf desselben erstellen. Möglicherweise müssen Sie die Funktionen lazyNew oder lazyGet verwenden.

In Bezug auf Ihre Frage zu dynamischen Entscheidungsfindung. Hier sind meine Gedanken, ich bin schon vor einiger Zeit auf diese Frage gestoßen. Aber ich habe nicht gesehen, was ich getan habe, also, was ich getan habe, wurde eine Fabrik in IncomingOrder Klasse injiziert, die Objekt erstellen kann. Das Gute daran ist, wenn Ihre Source-Analyse eine Art von Abhängigkeit benötigt, die Sie innerhalb der Fabrik verwenden können.

ZB:

<?php 
namespace Something; 

use Aura\Di\Container; 

class SourceFactory 
{ 
    public function __construct(Container $di) 
    { 
     $this->di = $di; 
    } 

    public function newInstance($source) 
    { 
     if ($di->has($source)) { 
      return $di->get($source); 
     } 
     // or alternatively create with new as done in switch 
    } 
} 

Hoffnung, das hilft.

Danke

+1

So in meiner Config I Definitionen für die verschiedene Quelle Parser setzen. Wenn ich dann richtig verstehe, wird die 'SourceFactory' in den 'IncomingOrder' injiziert und nach dem Quellen' $ sourceParser = $ this-> sourceFactory-> newInstance ($ source)'. Ich werde es versuchen. Vielen Dank. –

+1

Ja, Sie haben das gleiche Verständnis. –