services - symfony service loader
¿Cómo puedo acceder a un servicio fuera de un controlador con Symfony2? (2)
Estoy construyendo un sitio que depende bastante de una API de terceros, así que pensé que tendría sentido empaquetar la envoltura de API como un servicio, sin embargo, estoy empezando a encontrar instancias en las que sería útil tener acceso a ella. 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).
¿Alguien puede decirme si esto es posible y si no hay un enfoque sugerido para hacer este tipo de cosas?
Gracias por cualquier ayuda
La distribución de Symfony depende en gran medida de la inyección de dependencia. Esto significa que generalmente, 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 una entidad.
Lo que podría hacer es crear otro servicio que será responsable de hacer el trabajo que estaba a punto de hacer en el repositorio de la entidad. 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 maneras de compartir valores de configuración).
En mi caso de uso, uso un servicio de ayuda de Facebook que envuelve las llamadas a 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 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 at (@) en el archivo config.yml significa que Symfony debe inyectar otro servicio, que tiene el id definido después del signo at, y no una cadena simple. 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.
- Symfony Official DI
- Artículos de Fabien Potencier sobre DI
- Artículos de Richard Miller sobre DI (consulte en su blog los otros artículos de DI)
Tenga 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 te ayude a definir una solución final a tu problema. No dude en hacer otras preguntas si quiere aclaraciones o cualquier otra cosa.
Saludos, Matt
Me gustaría envolver este tipo de comportamiento en un servicio de Symfony (como un administrador). No inyectaría ningún parámetro o lógica en los repositorios de entidades, ya que deberían usarse principalmente para captar datos utilizando consultas de administrador de objetos. Me gustaría poner 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 obtener datos.