2016-02-09 55 views
0

我嘗試在我的RepositoryClass中注入Container,但它不起作用。在我的存儲庫類中注入容器

BaseRepository:

<?php 

namespace MyApp\ApplicationBundle\Repository; 

use Symfony\Component\DependencyInjection\ContainerAwareInterface; 
use Symfony\Component\DependencyInjection\ContainerInterface; 

class BaseRepository implements ContainerAwareInterface 
{ 

    protected $container; 

    public function setContainer(ContainerInterface $container=null) 
    { 
     echo "container"; 
     var_dump($container); 
    } 

    public function __construct() 
    { 
     echo __CLASS__; 
    } 
} 

services.yml

services: 
    myapp.base_repository: 
     class: MyApp\ApplicationBundle\Repository\BaseRepository 
     calls: 
      - [ setContainer, [ '@service_container' ] ] 

DefaultController:

$baseRep = new BaseRepository(); 

輸出的唯一,我得到的是回聲FILE從BaseRepository建設。 ,我試圖第二種方法,是注入GuzzleClient自我(這就是爲什麼我試圖注入容器,是因爲我需要我的狂飲,configuraton設置。

services.yml

myapp.base_repository: 
    class: MyApp\ApplicationBundle\Repository\BaseRepository 
    arguments: ['@csa_guzzle.client.mce'] 

BaseRepository:

use GuzzleHttp\Client; 

class BaseRepository 
{ 
    public function __construct(Client $client) 
    { 
     var_dump($client); 
     echo __CLASS__; 
    } 
} 

但後來我得到了以下錯誤:

Type error: Argument 1 passed to MyApp\ApplicationBundle\Repository\BaseRepository::__construct() must be an instance of GuzzleHttp\Client, none given, called in MyApp/src/Chameleon/DefaultBundle/Controller/DefaultController.php on line 20

任何人都知道我能做什麼?

謝謝!

+0

新運算符對依賴注入容器一無所知。您需要直接從容器中提取服務。從一個控制器將是$ repo = $ this-> get('myapp.base_repository'); – Cerad

+0

看過你在做什麼之後,似乎創建一個服務來執行你想要的操作會更有意義,並且如果需要調用存儲庫函數,則將實體管理器注入到該服務器中。 –

回答

1

要獲得由服務容器,你必須使用該容器與ID myapp.base_repository作爲Twifty獲得服務管理的類說:

$this->get('myapp.base_repository'); 
// or more generally in classes implementing ContainerAwareInterface: 
$this->container->get('myapp.base_repository'); 

如果你自己創建一個新的實例,你將有來管理所有的依賴關係:

// In your controller extending Symfony's Controller: 
$repository = new BaseRepository(); 
$repository->setContainer($this->container); 

同樣,如果你注入狂飲的客戶端進入你必須要麼檢索容器中的服務或自己與所有依賴關係創建庫:

// $this->get() assumes you are in the controller as well 
$repositoryWithClientFromServiceContainer = new BaseRepository(
    $this->get('csa_guzzle.client.mce') 
); 
// This obviously works everywhere 
$repositoryWithNewDefaultClient = new BaseRepository(
    new GuzzleHttp\Client() 
); 

此外,將服務容器注入到類中會違反您試圖通過首先使用服務容器來實現的依賴關係反轉。這意味着,您應該只添加您在該存儲庫中所需的服務,而不是使您的存儲庫爲ContainerAware,而不是整個容器。就像你在Guzzle-client的第二個例子中一樣。

有些人認爲控制器違反該原則是可以的,但我個人更喜歡controller's being defined as services能夠通過查看構造函數快速查看它們具有的依賴關係。

作爲一般規則,我會避免使用ContainerAwareInterface。

+0

同意你的一般規則。似乎作者的整個概念需要顛倒 - 創建一個服務並將實體管理器注入到該服務中。 –

0

Similarly if you inject a Guzzle-client into the repository you have to either retrieve the service from the container or create it yourself with all the dependencies:

// $this->get() assumes you are in the controller as well 
$repositoryWithClientFromServiceContainer = new BaseRepository(
    $this->get('csa_guzzle.client.mce') 
); 
// This obviously works everywhere 
$repositoryWithNewDefaultClient = new BaseRepository(
    new GuzzleHttp\Client() 
); 

Furthermore injecting the service container into a class violates the dependency inversion you try to achieve by using the Service Container in the first place. This means, instead of making your repository ContainerAware you should only add the services you need in that repository, not the whole container. Just as you do in the 2nd example with the Guzzle-client.

Some people argue it's okay for controllers to violate that principle, but I personally prefer [controller's being defined as services][1] to be able to quickly see which dependencies they have by looking at the constructor.

As a general rule I would avoid using the ContainerAwareInterface.

[1]: http://symfony.com/doc/current/cookbook/controller/service.html

謝謝。

因此,如果我只注入guzzleClient,那將是更好的解決方案,對吧? 正如你所看到的,我有幾個從BaseRepository擴展的類,他們需要guzzleClient。

但是如何爲這種情況注入guzzleClient?如果程序員只想在沒有任何參數的情況下在控制器中創建他的基本「MyRep」Repository類。

services.yml

myapp.base_repository: 
    class: MyApp\ApplicationBundle\Repository\BaseRepository 
    arguments: ['@csa_guzzle.client.mce'] 

BaseRepository:

use GuzzleHttp\Client; 
class BaseRepository 
{ 
    private $client = null; 
    public function __construct(Client $client) 
    { 
     var_dump($client); 
     $this->client = $client; 
    } 

    public getClient() { 
     return $this->client; 
    } 
} 

MyRepository:

MyRep extends BaseRepository: 
    use GuzzleHttp\Client; 
    class BaseRepository 
    { 
     public function __construct() 
     { 
      var_dump($this->getClient()); 
     } 
    } 

謝謝!

相關問題