2012-01-06 13 views
15

En mi controlador de Symfony2, esto funciona bien:Symfony2-Cómo utilizar el acceso a un servicio desde el exterior de un controlador

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

pero cuando lo muevo a un escucha personalizado:

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

consigo un error:

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

sé que debe necesitar una declaración uso pero don No sé qué usar.

+2

Esto debería proporcionar una posible solución: [¿Cómo obtengo dependencias de servicios en una clase personalizada] (http://stackoverflow.com/questions/8622382/how-do-i-get-services-dependencies-in-a-custom-class) – kufi

Respuesta

16

Actualización: la definición de controladores como servicios ya no se recomienda oficialmente en Symfony.

get() El método en la clase Controller es sólo un método de ayuda para obtener los servicios del contenedor, y que estaba destinado a conseguir nuevos desarrolladores Symfony2 a la velocidad más rápida. Una vez que las personas se sientan cómodas con el marco y la inyección de dependencia, se recomienda define controllers as services e inyectar cada servicio requerido explícitamente.

Dado que su clase PersonChange no es un controlador y no extiende la clase Controller, no tiene ese método de ayuda get(). En su lugar, debe definir su clase como un servicio e inyectar los servicios necesarios de forma explícita. Lee el Service Container chapter para más detalles.

+0

Literalmente la primera oración: la definición de controladores como servicios ** no es oficialmente recomendada ** por Symfony. –

+0

Han pasado 4 años desde mi respuesta. Las mejores prácticas evolucionan. –

+0

Sí, pero esta respuesta aún se encuentra fácilmente al buscar en Google. Debe actualizarse para estar en línea con las prácticas actuales de Symfony. –

12

Como me encontré con el mismo problema Tal vez pueda ayudar

Lo dijo Elnur es perfectamente bien y Voy a tratar para que aparezca un ejemplo de la vida real.

En mi caso yo quería acceder a la

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

Incluso extendiendo el controlador no pude conseguir que funcione mientras que el controlador tiene acceso al contenedor (yo todavía no entiendo por qué)

en config.yml mi oyente (searchindexer.listener) se declara como sigue:

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

Un servicio (ivory.lucene.search) se pasa como argumento a mi servicio/oyente.

Luego, en mi clase

protected $lucenemanager; 

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

continuación, puede utilizar el método get contra $ este

+0

muy buena respuesta! –

6

Un enfoque que siempre funciona, a pesar de no ser la mejor práctica en OO

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

Si necesita acceder a un Servicio, defínalo en el constructor de la clase:

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

Ahora usted puede pasar el servicio como argumento cuando se llama a la clase (ejemplo 1) o definir las clas como un Servicio (recomienda, ejemplo 2)

Ejemplo 1:

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

Ejemplo 2 (mejor):

definir PersonChange como servicio en sí, y definir el otro servicio como un argumento en el archivo services.yml:

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

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

De esta manera, usted no tiene que molestarse con el servicio upload_manager en el controlador, ya que está implícitamente pasa como argumento para el constructor, por lo que su controlador puede ser:

class appController{ 
    function buzzAction(){ 
     $personChange = $this->get('PersonChange'); 
Cuestiones relacionadas