2011-05-25 12 views
50

Estoy construyendo un sitio que depende bastante de una API de terceros, así que pensé que tendría sentido empaquetar el contenedor API como un servicio, sin embargo, estoy empezando a encontrar instancias en las que sería útil tener acceso fuera de un controlador, como en un repositorio de entidades. También relacionado con eso, sería útil poder acceder a los valores de configuración fuera de un controlador (de nuevo, como en un repositorio de entidades).¿Cómo puedo acceder a un servicio fuera de un controlador con Symfony2?

¿Alguien puede decirme si esto es posible y si no hay un enfoque sugerido para hacer este tipo de cosas?

gracias por cualquier ayuda

Respuesta

73

La distribución de Symfony se basa principalmente en la inyección de dependencia. Esto significa que, por lo general, las dependencias se inyectan directamente en su objeto a través del constructor, los instaladores o por otros medios (como la reflexión sobre las propiedades). Su servicio contendor API es entonces una dependencia para otros objetos de su aplicación.

Dicho esto, sería bastante difícil inyectar este servicio en el constructor de un repositorio de entidades porque ya requiere algunos otros parámetros y creo que no sería posible inyectarlos debido a la forma en que solicitamos el repositorio para un entidad.

Lo que podrías hacer es crear otro servicio que será responsable de hacer el trabajo que estabas a punto de hacer en el repositorio de entidades. De esta forma, podrá inyectar el administrador de entidades, que se usará para recuperar el repositorio de entidades, su servicio personalizado y también otro servicio que contenga sus valores de configuración (existen otras formas de compartir valores de configuración).

En mi caso de uso, uso un servicio de ayuda de Facebook que envuelve las llamadas de la API de Facebook. Este servicio luego se inyecta donde lo necesito. El repositorio de mi entidad solo es responsable de realizar llamadas a la base de datos, por lo que solo recibe los argumentos que necesita y no toda la dependencia. Por lo tanto, no recibirá el asistente, sino solo los argumentos necesarios para realizar una solicitud, por ejemplo, una identificación de usuario de Facebook. En mi opinión, esta es la manera de hacerlo, ya que creo que el repositorio de la entidad no debería tener dependencias en dichos objetos auxiliares.

Aquí un pequeño ejemplo usando YAML como la configuración:

# app/config/config.yml 
services: 
    yourapp.configuration_container: 
    class: Application/AcmeBundle/Common/ConfigurationContainer 
    # You could inject configurations here  

    yourapp.api_wrapper: 
    class: Application/AcmeBundle/Service/ApiWrapperService 
    # Inject other arguments if needed and update constructor in consequence  

    yourapp.data_access: 
    class: Application/AcmeBundle/Data/Access/DatabaseAccessService 
    arguments: 
     entityManager: "@doctrine.orm.entity_manager" 
     apiWrapperService: "@yourapp.api_wrapper" 
     configuration: "@yourapp.configuration_container" 

# Application/AcmeBundle/Common/ConfigurationContainer.php 
public ConfigurationContainer 
{ 
    public function __construct() 
    { 
     // Initialize your configuration values or inject them in the constructor 
    } 
}   

# Application/AcmeBundle/Service/ApiWrapperService.php 
public ApiWrapperService 
{ 
    public function __construct() 
    { 
     // Do some stuff 
    } 
} 

# Application/AcmeBundle/Data/Access/DatabaseAccessService.php 
public DatabaseAccessService 
{ 
    public function __construct(EntityManager $entityManager, ApiWrapperService $apiWrapperService, ConfigurationContainer $configuration) 
    { 
     ... 
    } 
} 

El signo (@) en el archivo config.yml significa que Symfony debe inyectar otro servicio, que tiene la Identificación del definido después de la arroba, y no una simple cadena. Para los valores de configuración, como dije anteriormente, hay otros medios para lograr el mismo objetivo, como usar parámetros o una extensión de paquete. Con una extensión de paquete, podría definir los valores de configuración directamente en config.yml y su paquete los leería.

En conclusión, esto debería darle la idea general de los servicios de inyección. Aquí una pequeña lista de documentación sobre el tema. Muchos enlaces usan la definición del servicio XML en lugar de la definición YAML, pero debería poder entenderlos con bastante facilidad.

  1. Symfony Official DI
  2. Fabien Potencier's articles on DI
  3. Richard Miller's articles on DI (Compruebe en su blog para los demás artículos DI)

tomar en cuenta que la configuración que estoy dando está trabajando para Beta1 de Symfony2. No actualicé aún a Beta2, por lo que podría haber algunas cosas que no funcionan, ya que están en la versión Beta2.

Espero que esto lo ayude a definir una solución final a su problema. No dude en hacer otras preguntas si quiere aclaraciones o cualquier otra cosa.

Saludos, Matt

+0

Esto es una gran ayuda, tengo mi servicio de API que se inyecta en mi servicio de base de datos que es genial, todavía no estoy del todo claro sobre cómo proceder con la configuración. Podría ser mejor si explico lo que trato de hacer. Estoy construyendo un sitio que funcionará en varios dominios, cada sitio existirá como un entorno con su propio archivo de configuración yaml. En el archivo de configuración será una identificación del sitio, lo que quiero es poder llamar a getUsers() por ejemplo y para obtener el id del sitio desde la configuración y agregar automáticamente un "where site_id = x" a la consulta. ¿Es eso posible o debería pasar la identificación como parámetro? – pogo

+1

Acabo de darme cuenta de que el artículo de Symfony al que me has vinculado explica cómo hacerlo, gracias de nuevo por la ayuda. Esto me ha estado estresando por un par de días, así que es genial tener una solución. – pogo

+0

Me alegra que ayude y que ahora tiene una solución a su problema :) De hecho, el artículo que he vinculado es más explícito sobre cómo usar parámetros y cosas así. Buena suerte con tu trabajo. – Matt

0

Me envolver este tipo de comportamiento en un servicio de Symfony (similar a la administración). No inyectaría ningún parámetro o lógica en los repositorios de entidades, ya que deberían utilizarse principalmente para obtener datos mediante consultas de gestor de objetos. Pondría la lógica en los servicios y si el servicio requiere un acceso a la base de datos, llamará al repositorio de la entidad para buscar datos.

Cuestiones relacionadas