2016-04-08 11 views
3

Slim Framework 3を使用しています。に定義されている$loggerをRouter Controllerクラスに注入したいとします。私がしていることは以下の通りです。よりよい方法はありますか?スリムフレームワーク3ドキュメントで

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'); 
    } 
} 

、ルートコントローラを使用しての適切な方法は、次のようになります。

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

しかし、どのように私はを注射するのですか?をAccountControllerに追加すると、ルートコントローラーをよりエレガントな方法でコーディングすることができます。

答えて

3

container resolution docsによると、あなたは、コントローラの内部で、コンテナを通して、あなたのロガーにアクセスできるようにする必要があります

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'); 
    } 
} 

あなたが$app->get('/test', 'AccountController:test');を呼び出すと、スリムは自動的にAccountControllerにコンテナを渡す必要がありますのコンストラクタ。

これは、と言われていますが、これは素晴らしいデザインの例よりも便利な機能です。 Rob Allenが解答で説明したように、コンテナをそれぞれに挿入するのではなく、コントローラーをアプリケーションコンテナに注入することで、より良いモジュール性と簡単にテストされたコードを実現できます(単位テストを使用する場合)コントローラ。

彼のexample Slim applicationを見てください。例えば、AuthorControllerのように見れば、このデザイン・コントローラ・クラスがどのようにすべてのサービスを提供する魔法のコンテナに依存していないかを見ることができます。代わりに、を明示的に指定します。各コントローラはコンストラクタで必要となります。これは、テストシナリオで個々の依存関係をより簡単に模擬できることを意味します。

+0

ありがとうございます!どのように私はその情報を欠場することができます!私はコンテナを持っています:function __construct(Slim \ Container $ ci) –

+0

これはあなたのコントローラにロガーを注入する正しい方法ではありません。この例では、コンテナ自体を注入します。それは正しい方法ではありません。私はロブの答えをチェックすることができます。 http://stackoverflow.com/a/36517681/721600 – hkulekci

+1

@hkulekciはい、私は残りの答えに言及しました。 – alexw

3

コントローラをテストしやすくするために、コンストラクタを介してコントローラにロガーを注入する必要があります。

AccountControllerは次のようになります。

$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'); 

その後、あなたが作る場合は、フォーマットのルート呼び出し可能に'class name' colon 'method name'の文字列であることに注意してください、スリム:

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']); 
    } 
} 
のindex.phpに設定し

のようなものです3は、DIコンテナからコントローラクラスを抽出した後、メソッドを呼び出します。クラス名がコンテナに登録されたキーでない場合、クラス名はインスタンス化されコンテナに渡されます。

関連する問題