2012-01-06 99 views
15

在我的Symfony2控制器,這工作得很好:Symfony2中,如何使用訪問的服務從控制器外部

$uploadManager = $this->get('upload.upload_manager'); 

但是當我移動到一個自定義的監聽器:

use Doctrine\ORM\Event\LifecycleEventArgs; 
use Acme\UploadBundle\Upload\UploadManager; 

class PersonChange 
{ 
    public function postRemove(LifecycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 
     $entityManager = $args->getEntityManager(); 

     $uploadManager = $this->get('ep_upload.upload_manager'); 
     echo "the upload dir is " . $uploadManager->getUploadDir(); 
    } 
} 

我得到一個錯誤:

Fatal error: Call to undefined method Acme\MainBundle\Listener\PersonChange::get() in /home/frank/... 

我知道我必須需要一個使用聲明,但不要不知道該用什麼。

+2

這應該提供一個可能的解決方案:[如何獲得自定義類中的服務依賴項](http://stackoverflow.com/questions/8622382/how-do-i-get-services-dependencies-in-a-custom-class) – kufi 2012-01-06 12:54:01

回答

16

更新:在Symfony中不再正式推薦將控制器定義爲服務。

Controller類的get()方法只是一種輔助方法,從容器獲得服務,這是爲了獲得新的Symfony2的開發商多達速度。 一旦人們對框架和依賴注入感到滿意,建議使用define controllers as services並明確注入每個必需的服務。

由於您的PersonChange類不是控制器,並且沒有擴展Controller類,因此您沒有該幫助方法get()。相反,您需要將您的類定義爲服務並明確注入所需的服務。詳情請閱讀Service Container chapter

+0

字面上第一句:將控制器定義爲服務**不是由Symfony正式推薦**。 – 2016-09-06 14:23:02

+0

我的答案已經過去了4年。最佳實踐發展。 – 2016-09-06 20:51:44

+0

是的,但當谷歌搜索時,這個答案仍然很容易找到。它應該更新以符合當前的Symfony實踐。 – 2016-09-07 12:23:34

12

當我跑進了完全相同的問題,也許我可以幫

埃裏烏爾說的是完全沒有問題,我會只是嘗試彈出一個活生生的例子。

在我的情況,我想即使通過擴展控制器我無法得到它,而控制器不訪問容器的工作訪問

$lucenemanager = $this->get('ivory.lucene.manager') 

(我仍然不明白爲什麼)

在config.yml我的聽衆(searchindexer.listener)聲明如下:

services: 
    searchindexer.listener: 
     class: ripr\WfBundle\Listener\SearchIndexer 
     arguments: 
       luceneSearch: "@ivory_lucene_search" 
     tags: 
      - { name: doctrine.event_listener, event: postPersist } 

服務(ivory.lucene.search)作爲我的服務/監聽器參數傳遞。

然後在我的課

protected $lucenemanager; 

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

然後你可以使用GET方法對$此

+0

很好的答案! – 2012-11-22 12:35:54

6

的一種方法永遠奏效,儘管不是在OO

global $kernel; 
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');‏ 
1

的最佳實踐如果您需要訪問一個服務,在類的構造函數定義它:

class PersonChange{ 
    protected $uploadManager; 
    public function __construct(UploadManager $uploadManager){ 
     $this->uploadManager = $uploadManager; 
    } 
    // Now you can use $this->uploadManager. 
} 

現在可以調用類(實施例1)時傳遞服務作爲參數或限定CLAS本身作爲服務(推薦,實施例2)

實施例1:

use Acme\PersonChange; 
class appController{ 
    function buzzAction(){ 
     $uploadManager = $this->get('upload.upload_manager'); 
     $personChange = new PersonChange($uploadManager); 

實施例2 (優於)

定義PersonChange作爲服務本身,並定義其他服務,如文件services.yml一個參數:

# app/config/services.yml 
services: 
    upload.upload_manager: 
     class:  AppBundle\uploadManager 

    PersonChange: 
     class:  AppBundle\PersonChange 
     arguments: ['@upload.upload_manager'] 

通過這種方式,你不必與控制器的upload_manager服務打擾,因爲它是作爲構造函數的參數隱含過去了,所以你的控制器可以是:

class appController{ 
    function buzzAction(){ 
     $personChange = $this->get('PersonChange'); 
相關問題