Nuevo en Symfony 2.7: mejoras en la Inyección de Dependencias
El componente DependencyInjection permite centralizar la creación de los objetos en las aplicaciones PHP. Symfony utiliza este componente para crear su contenedor de servicios, que es el máximo responsable de que el framework Symfony sea tan extensible y se adapte a cualquier necesidad que tengas. En Symfony 2.7 se ha mejorado este componente añadiendo nuevas funcionalidades y eliminando algunas funcionalidades existentes.
Añadido soporte para crear alias automáticos
Esta nueva funcionalidad ha surgido a partir de las necesidades del proyecto Drupal. El problema a resolver era el siguiente: considerando los siguientes servicios:
lock: class: Drupal\Core\Lock\Lock... mysql.lock: class: Drupal\Core\Lock\Lock... sqlite.lock: class: Drupal\Core\Lock\Lock...
La idea es que cuando el administrador del sitio cambia por ejemplo el valor de la opción de configuración default_backend
a mysql
, el servicio genérico lock
debería ser un alias del servicio mysql.lock
.
En Symfony 2.7 se ha creado un nuevo compiler pass llamado auto_alias
que permite hacer precisamente esto. Para ello, simplemente aplica a tu servicio la nueva etiqueta auto_alias
y define el formato del alias (puedes usar cualquier parámetro del contendor para definir el valor del alias):
# app/config/services.yml lock: class: Drupal\Core\Lock\Lock... tags: - { name: auto_alias, format: "%default_backend%.lock" }
Esta funcionalidad ha sido desarrollada por Daniel Wehner en el pull request #12526 de Symfony.
Mejorada la creación de servicios inline en el dumper XML
Para mejorar el rendimiento de la aplicación, el contenedor de servicios busca todos los servicios privados que solamente se utilizan una vez. Después, elimina esos servicios y e incluye su código directamente dentro del único servicio que los utilizan. Técnicamente eso se conoce como crear servicios "inline".
Por otra parte, cuando se crea la caché de la aplicación Symfony, el contenedor se vuelca a un archivo XML utilizando lo que se conoce como el XML dumper (mira por ejemplo el archivo appDevDebugProjectContainer.xml
dentro del directorio app/cache/
de cualquier aplicación Symfony que tengas).
No obstante, este volcado del contenedor a XML tenía dos limitaciones que impedían crear servicios inline: cuando usas un configurador de servicios y cuando defines una factoría privada usando la nueva sintaxis de las factorías.
En Symfony 2.7 todos estos problemas desaparecen y el contenedor es capaz ahora de crear servicios inline en todos los casos, lo que aumenta muy ligeramente el rendimiento de la aplicación.
Esta funcionalidad ha sido desarrollada por Christian Flothmann en el pull request #14030 de Symfony.
Improved YAML service definition syntax
YAML es uno de los tres formatos de configuración que se pueden usar para definir los servicios en las aplicaciones Symfony. En las versiones actuales de Symfony, cuando defines un servicio complejo con YAML, tiene la siguiente pinta:
# app/config/services.yml services: manager: class: AppBundle\Manager\UserManager arguments: [true] calls: - [setLogger, ["@logger"]] - [setClass, ["User"]] tags: - { name: twig.extension, alias: user }
En Symfony 2.7 se ha mejorado la sintaxis YAML para que puedas usar una configuración más expresiva si así lo prefieres (por supuesto el anterior formato sigue funcionando perfectamente):
# app/config/services.yml services: manager: class: AppBundle\Manager\UserManager arguments: - true calls: - method: setLogger arguments: - "@logger" - method: setClass arguments: - User tags: - name: manager alias: user
Esta funcionalidad ha sido desarrollada por Martin Hasoň en el pull request #13892 de Symfony.
Los servicios sincronizados se han declarado obsoletos
En las aplicaciones Symfony, un servicio no puede depender de otros servicios cuyo scope sea más restringido. En la práctica esto significa que si intentas inyectar el servicio request
en cualquier otro servicio, verás un error de tipo ScopeWideningInjectionException
.
Symfony 2.3 introdujo el concepto de servicios sincronizados para tratar de resolver este problema. Por eso el servicio request
está definido como de tipo synchronized
:
services: request: scope: request synchronized: true # ...
De esta manera ahora sí que puedes inyectar el servicio request
usando la inyección mediante setter:
namespace AppBundle\Mail; use Symfony\Component\HttpFoundation\Request; class Mailer { protected $request; public function setRequest(Request $request = null) { $this->request = $request; } // ... }
# app/config/services.yml services: mailer: class: AppBundle\Mail\Mailer calls: - [setRequest, ["@?request"]]
En cualquier caso, el verdadero problema es que request
no debería ser un servicio, ya que la petición debería ser simplemente un value object. En Symfony 3 este problema se solucionará de una vez por todas porque desaparece el servicio request
.
Mientras tanto, en Symfony 2.7 se han declarado obsoletos los servicios sincronizados, porque también se van a eliminar en Symfony 3. El motivo es que es una funcionalidad bastante compleja que realmente no necesitamos y además, no es la forma correcta de solucionar el problema. La solución alternativa, como seguramente sabes, es inyectar el servicio request_stack
en vez de request
.
Esta funcionalidad ha sido desarrollada por Fabien Potencier en el pull request #13289 de Symfony.
Comentarios
Este artículo ya no permite añadir más comentarios.
¿Por qué? Los artículos cierran sus comentarios automáticamente
unos meses después de su publicación para asegurar que estos sigan
siendo relevantes.
Proyectos Symfony destacados
La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más
Síguenos en @symfony_es para acceder a las últimas noticias.