2

Wie Dependency Injection Container verwenden, wenn ich einen variablen nicht statischen Parameter habe, den ich liefern muss? dieseWie platziert man eine Klasse, die einen Variablenparameter benötigt, in den Dependency-Injection-Container?

Was ich in meinem Code möchte, ist:

$staff = $container->get(Staff::class); 

Was ich jetzt habe, ist dies:

$staff = new Staff("my_great_username"); 

Beachten Sie, dass Benutzernamen ändern kann und wird zur Laufzeit geliefert .

Ich kann nicht scheinen Staff in meinem DI-Container zu setzen, weil es dort keine Möglichkeit gibt, einen Variablenparameter anzugeben.

Mein Problem ist ...

Ich bin mit Fabrik-basierten Container, nämlich Zend\ServiceManager\ServiceManager .Dies ist eine Fabrik, die ich Details zu verstecken Instanziierung verwenden:

class StaffFactory 
{ 
    function __invoke(ContainerInterface $container): Staff 
    { 
     /* 
     * I do not seem to know how to get my username here 
     * nor if it is the place to do so here 
     */ 
     $staff = new Staff(????????); 
     return $staff; 
    } 
} 

So wie ich gesetzt bis den Behälter in meiner Config ist dies:

'factories' => [ 
    Staff::class => StaffFactory::class 
] 

Hinweis: auch wenn der Parameter eine "Variable" ist, ich will Staff unveränderlich sein. Sobald es einmal erstellt ist, bleibt es so. Daher möchte ich nicht speziell eine setter Methode für den Benutzernamen machen, da dies bedeutet, dass die Klasse veränderbar ist, wenn dies nicht der Fall ist.

Was schlagen Sie vor?

+0

Wenn Sie das auch stümpfen, upvote diese Frage xD – Dennis

+0

Ich bin verwirrt - warum verwenden Sie den IOC-Container als Service-Locator und insbesondere mit konkreten Klassen - so scheint es keinen Vorteil gegenüber 'neu zu haben ' – Steve

+0

Wo sehen Sie die Verwendung von IoC als Service-Locator? Wie ich es verstehe, wird es nur zu einem Service-Locator, wenn ich '$ container' in meine eigenen Klassen injiziere, wo ich dann ziehen kann, was immer ich will.Da 'ServiceManager' ein werkbasierter IoC ist, solange ich' $ container' als Teil des Boot-Strap benutze, bleibt es ein IoC. aka, "$ container" in Factory zu injizieren, ist ein akzeptierter Anwendungsfall für IoC, und diese Injektion bleibt in dieser Factory lokalisiert und fließt nicht in meine eigenen Klassen ein, wodurch Service-Locator-Muster vermieden werden. – Dennis

Antwort

1

Mein Problem war, dass ich einen Variablenparameter hatte, der an den Konstruktor meiner Klasse Staff übergeben wurde.

Die Lösung besteht darin, eine StaffCreator-Klasse zu erstellen, die keine Variablenparameter in ihrem Konstruktor hat, und dann eine StaffCreator::create-Methode schreiben, die den Variablenparameter verwendet. Anstatt Staff in jede Klasse zu injizieren, in der Staff benötigt wird, injizieren Sie stattdessen StaffCreator und verwenden Sie sie dann, um eine Staff Instanz zu erstellen.

heißen

//Inject this wherever you need Staff 
$staffCreator = $container->get(StaffCreator::class); 

//use it: 
$staff = $this->staffCreator->create("my_great_username"); 

//code: 
class StaffCreatorFactory 
{  
    function __invoke(ContainerInterface $container) 
    { 
     return new StaffCreator(); 
    } 
} 

class StaffCreator 
{ 
    function __construct() 
    { 
     //additional creation parameters possible here 
    } 

    function create(string $username): Staff 
    { 
     return new Staff($username); 
    } 
} 

mit Kredit Steve

Hinweis: Sie können Interfaces den obigen Code erstellen und in der DI wiederverwendbar zu machen. d.h. StaffCreatorInterface, StaffInterface. In meinem Fall habe ich es einfach gehalten, da ich (noch) keinen starken Anwendungsfall für die Wiederverwendung der Schnittstelle habe.

Verwandte Themen