2016-04-08 7 views
3

Ich benutze Slim Framework 3. Ich möchte $logger in dependencies.php in eine Router Controller-Klasse injizieren. Unten ist was ich tue, gibt es einen besseren Weg?

routes.php

$app->get('/test', function($request, $response, $args){ 
    $controller = new AccountController($this->get('logger')); 
    return $controller->test($request, $response, $args); 
}); 

AccountController

class AccountController{ 

    private $logger; 
    function __construct($logger){ 
     $this->logger = $logger; 
    } 

    public function test($request, $response, $args){ 
     $this->logger->info('i am inside controller'); 
     return $response->withHeader('Content-Type', 'application/json')->write('test'); 
    } 
} 

In Schlanke Rahmen 3-Dokumentation sollte die richtige Art und Weise einer Route-Controller zu verwenden sein:

$app->get('/test', 'AccountController:test'); 

Aber wie spritze ich $logger in AccountController, wenn ich meinen Route Controller auf diese "elegantere" Weise codiere?

Antwort

3

Nach dem container resolution docs, sollten Sie in der Lage sein, Ihre Logger durch den Behälter zu gelangen, in Ihrem Controller:

AccountController

class AccountController 
{ 
    protected $ci; 

    //Constructor 
    public function __construct(ContainerInterface $ci) 
    { 
     $this->ci = $ci; 
    } 

    public function test($request, $response, $args) 
    { 
     $this->ci->get('logger')->info('i am inside controller'); 
     return $response->withHeader('Content-Type', 'application/json')->write('test'); 
    } 
} 

Wenn Sie $app->get('/test', 'AccountController:test'); nennen, Schlank automatisch den Behälter in AccountController passieren sollte 's Konstruktor.

Das sagte, das ist eher eine Bequemlichkeit als ein Beispiel für gutes Design. Wie Rob Allen in seiner Antwort erklärt, können Sie eine bessere Modularität und somit einen leichter zu testenden Code erreichen (wenn Sie Komponententests verwenden), indem Sie die Controller in den Anwendungscontainer injizieren, anstatt den Container in jeden zu injizieren Regler.

Werfen Sie einen Blick auf seine example Slim application. Wenn Sie zum Beispiel AuthorController betrachten, können Sie sehen, wie mit diesem Design-Controller-Klassen nicht mehr auf den magischen Container angewiesen sind, der alle Dienste bereitstellt. Stattdessen geben Sie explizit die Dienste, die jeder Controller im Konstruktor benötigt. Dies bedeutet, dass Sie die einzelnen Abhängigkeiten in Testszenarien einfacher darstellen können.

+0

Danke! Wie kann ich diese Information verpassen? Ich habe den Container durch: Funktion __construct (Slim \ Container $ ci) –

+0

Dies ist nicht die richtige Art, Logger zu Ihrem Controller zu injizieren. Weil Sie in diesem Beispiel den Container selbst injizieren. Es ist nicht der richtige Weg.Du kannst Robs Antwort überprüfen, denke ich. http://Stackoverflow.com/a/36517681/721600 – hkulekci

+1

@hkulekci Ja, ich erwähnte das im Rest meiner Antwort. – alexw

3

Im Hinblick auf die Testfähigkeit Ihres Controllers sollten Sie den Logger über den Konstruktor in den Controller einspeisen.

Account sieht wie folgt aus:

class AccountController 
{ 
    protected $logger; 

    public function __construct($logger) { 
     $this->logger = $logger; 
    } 

    public function test($request, $response, $args){ 
     $this->logger->info('i am inside controller'); 
     return $response->withJson(['foo' => 'bar']); 
    } 
} 

in index.php Die Einrichtung ist so etwas wie:

$container = $app->getContainer(); 
$container[Logger::class] = function ($c) { 
    $logger = new \Monolog\Logger('logger'); 
    return $logger; 
}; 
$container[AccountController::class] = function ($c) { 
    $logger = $c->get(Logger::class); 
    return new AccountController($logger); 
}; 

$app->get('/test', 'AccountController:test'); 

Beachten Sie, wenn Sie das Format Route eine Reihe von 'class name' colon 'method name' aufrufbar sein zu machen, dann nehmen 3 ruft nach dem Extrahieren der Controller-Klasse aus dem DI-Container die Methode für Sie auf. Wenn der Klassenname kein registrierter Schlüssel für den Container ist, instanziiert er ihn und übergibt den Container an den Konstruktor.