2012-01-06 37 views
15

Trong điều khiển Symfony2 của tôi, điều này hoạt động tốt:Symfony2-Làm thế nào để sử dụng truy cập một dịch vụ từ bên ngoài của một bộ điều khiển

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

nhưng khi tôi di chuyển nó đến một Listener tùy chỉnh:

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

Tôi nhận được thông báo lỗi:

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

Tôi biết tôi phải cần một tuyên bố sử dụng nhưng không 't biết những gì để sử dụng.

+2

nên này cung cấp một giải pháp có thể: [Làm thế nào để tôi nhận được các phụ thuộc dịch vụ trong một lớp tùy chỉnh] (http://stackoverflow.com/questions/8622382/how-do-i-get-services-dependencies-in-a-custom-class) – kufi

Trả lời

16

Cập nhật: Xác định bộ điều khiển dưới dạng dịch vụ không còn được đề xuất chính thức trong Symfony nữa.

Phương thức get() trong lớp Controller chỉ là phương thức trợ giúp để nhận các dịch vụ từ vùng chứa và điều này có nghĩa là để các nhà phát triển Symfony2 mới có tốc độ nhanh hơn. Một khi mọi người cảm thấy thoải mái với khuôn khổ và sự phụ thuộc tiêm, nó được khuyến khích để define controllers as services và tiêm mỗi dịch vụ yêu cầu một cách rõ ràng.

Vì lớp PersonChange của bạn không phải là bộ điều khiển và không mở rộng lớp Controller, bạn không có phương thức trợ giúp get(). Thay vào đó, bạn cần xác định lớp của bạn là một dịch vụ và tiêm các dịch vụ cần thiết một cách rõ ràng. Đọc số Service Container chapter để biết chi tiết.

+0

Nghĩa đen câu đầu tiên: Xác định bộ điều khiển là dịch vụ ** không chính thức được đề xuất ** bởi Symfony. –

+0

4 năm trôi qua kể từ khi tôi trả lời. Các phương pháp hay nhất phát triển. –

+0

Có, nhưng câu trả lời này vẫn dễ dàng tìm thấy khi Google. Nó sẽ được cập nhật để phù hợp với các thực hành Symfony hiện tại. –

12

Như tôi đã chạy vào cùng một vấn đề chính xác có lẽ tôi có thể giúp

gì Elnur nói là hoàn toàn tốt đẹp và tôi sẽ chỉ cố gắng bật lên một ví dụ thực tế đời sống.

Trong trường hợp của tôi, tôi muốn truy cập

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

Thậm chí bằng cách mở rộng điều khiển tôi không thể có được nó để làm việc trong khi bộ điều khiển không truy cập vào container (tôi vẫn không hiểu tại sao)

trong config.yml nghe tôi (searchindexer.listener) được khai báo như sau:

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

Một dịch vụ (ivory.lucene.search) được thông qua như là đối số trong dịch vụ của tôi/người nghe.

Sau đó, trong lớp học của tôi

protected $lucenemanager; 

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

Sau đó, bạn có thể sử dụng phương thức get chống lại $ này

+0

câu trả lời rất hay! –

6

Một cách tiếp cận mà luôn luôn làm việc, mặc dù không phải là người thực hành tốt nhất trong OO

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

Nếu bạn cần truy cập Dịch vụ, hãy xác định nó trong hàm tạo lớp:

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

Bây giờ bạn có thể vượt qua Dịch vụ như là đối số khi gọi lớp (ví dụ 1) hoặc xác định Clas bản thân như một dịch vụ (khuyến, ví dụ 2)

Ví dụ 1:

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

Ví dụ 2 (tốt hơn):

xác định PersonChange như một dịch vụ riêng của mình, và xác định các dịch vụ khác như một cuộc tranh cãi trong tập tin services.yml:

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

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

Bằng cách này, bạn không cần phải bận tâm với dịch vụ upload_manager trong điều khiển, vì nó implicitely thông qua như là một cuộc tranh cãi cho các nhà xây dựng, vì vậy điều khiển của bạn có thể là:

class appController{ 
    function buzzAction(){ 
     $personChange = $this->get('PersonChange'); 
Các vấn đề liên quan