Introducción
¡Hola, amigos! Bienvenidos a un nuevo curso sobre los Atributos de Inyección de Dependencia. ¿Qué son los Atributos de Inyección de Dependencia? Bueno, aquí tienes una pequeña lección de historia:
Breve historia de la inyección de dependencias en Symfony
Hace mucho tiempo, en una versión de Symfony muy, muy lejana, los servicios (que son objetos que funcionan) tenían que configurarse en archivos YAML o XML independientes. Los chicos guays lo llamaban "cablear un servicio". En estos archivos, creábamos un ID de servicio, hacíamos referencia a nuestra clase de servicio y, a continuación, hacíamos referencia a cualquier ID de servicio, parámetro o valor escalar que fuera necesario. Aunque esto funcionaba muy bien, era un poco engorroso. Cada vez que necesitábamos añadir, eliminar o modificar los argumentos de un servicio, teníamos que saltar a otro archivo de configuración y actualizarlo también. Seguro que podríamos encontrar una forma mejor de hacerlo, ¿verdad? ¡Seguro que sí!
En una versión posterior de Symfony, hace todavía mucho tiempo, añadieron algo llamado "autocableado". Esto nos permitía simplemente crear un objeto de servicio PHP, y cualquier otro servicio necesario se inyectaría automáticamente. Sólo teníamos que teclear la clase o interfaz del servicio. Aunque esto supuso un gran avance, aún teníamos que configurarlo en YAML o XML, incluso en escenarios ligeramente más avanzados (como argumentos escalares de un parámetro). Definitivamente redujo la cantidad de tiempo invertido en archivos de configuración, pero no lo eliminó.
Todo mejoró con PHP 8
Entonces llegó PHP 8 y añadió los atributos nativos, metadatos que pueden añadirse a las propiedades de las clases, métodos, argumentos de métodos y mucho más. Esta fue la característica perfecta para permitirnos hacer toda la configuración directamente en nuestras clases de servicio. Con Symfony 7.1 - la versión que usaremos en este curso - hay una plétora de atributos DI que usar, y echaremos un vistazo a cada uno de ellos. Veremos que la edición de un archivo de configuración independiente sólo es necesaria en escenarios raros y superavanzados. En la mayoría de los casos, el archivo services.yaml, que se incluye en cada nueva aplicación Symfony, es todo lo que necesitaremos, y casi nunca cambiará. Mostraremos todos estos atributos en una pequeña y divertida aplicación para que puedas ver cómo funcionan.
El problema
Este es el escenario: Tenemos un televisor inteligente, pero hemos perdido el mando a distancia. Lo hemos buscado por todas partes, pero no lo encontramos. Seguro que esos molestos gnomos del mando se lo llevaron para venderlo en "Gnomeslist"...
Hemos encontrado un mando de repuesto en Internet, pero está pendiente de entrega y tardará una eternidad en llegar. ¿Qué hacemos? Bueno, mientras buscábamos una solución en "RemoteOverflow.com", un usuario (que definitivamente no es un gnomo) nos habló de una API que existe para nuestra smart TV. Como desarrolladores web, podemos utilizar esa API para crear nuestro propio mando a distancia al que podamos acceder y utilizar en cualquier tableta conectada a nuestra red doméstica. Menos mal que los gnomos no nos robaron la tableta, ¿verdad? ¿Verdad?
Instala la aplicación
Para codificar conmigo, descarga el código del curso de este vídeo, ábrelo en el IDE que prefieras y sigue los pasos de configuración del archivo README.md. Yo ya lo he hecho. Ahora podemos ir a nuestro terminal y ejecutar
symfony serve -d
para ejecutar el servidor en segundo plano. Mantén pulsado "comando" y haz clic en la URL de aquí para abrir nuestra aplicación en el navegador, y... ¡ahí está nuestro mando a distancia! Hace todas las cosas habituales de un mando a distancia, como cambiar de canal, encender y apagar el televisor, y subir o bajar el volumen. Eso es todo por ahora. Si pasamos al código, es una aplicación Symfony 7.1 casi lista para usar.
Recorrido por la aplicación
Tenemos un único controlador - RemoteController - y una única ruta - home. Este controlador se encarga de renderizar la interfaz de usuario y de los clics en los botones. Cuando se pulsa un botón, gestionamos la lógica de los distintos botones (representada por un dump()), añadimos el mensaje flash y redirigimos a la misma ruta. Si no está gestionando un clic de botón, renderiza este index.html.twig. Esa es nuestra plantilla remota.
En nuestro directorio templates/, echemos un vistazo rápido a base.html.twig. Proviene de una instalación estándar de Symfony. La interfaz de usuario está diseñada con CSS de Tailwind, pero estoy haciendo algo un poco diferente a lo que estás acostumbrado. En lugar de instalar un sistema de gestión de activos como AssetMapper o Webpack Encore, utilizo la CDN de CSS de Tailwind para simplificar las cosas. Esto inyecta un poco de JavaScript en tu página que lee todas las clases de Tailwind que estás utilizando en tu HTML. Luego construye un archivo CSS personalizado y lo inyecta, estilizando el HTML. Como puedes imaginar, esto es un poco lento y nunca debería utilizarse en producción. Para la creación de prototipos y nuestros propósitos, es bastante fácil de poner en marcha y funciona muy bien.
Ahora, si echamos un vistazo a index.html.twig, ésta es nuestra plantilla remota real. Es bastante estándar, y puedes ver las clases Tailwind que estamos utilizando. Aquí es donde estamos renderizando nuestro mensaje flash, si existe, y aquí están los botones reales. Están envueltos en un <form> en el que cada <button>envía el formulario con el nombre del botón en el que se ha hecho clic. Lo único que no es estándar es esta etiqueta <twig:ux:icon ...>. Se trata de una combinación de dos paquetes de terceros que forman parte de la Iniciativa Symfony UX.
Iconos UX
En primer lugar, estamos utilizando symfony/ux-icons. Este paquete te permite añadir archivos .svg a este directorio assets/icons. Ahora, puedes incrustar estos SVG en Twig utilizando el nombre del archivo (menos el .svg) como atributo name en esta etiqueta. También puedes añadir atributos adicionales como los que tenemos aquí: height width , class, etc. Éstos se añadirán al elemento <svg> incrustado. Este paquete también hace otras cosas increíbles, así que busca en Google "Symfony UX Icons" para saber más sobre él
Componentes Twig
La otra parte de esta etiqueta <twig:ux:icons ...> es la propia etiqueta. Proviene del paquete symfony/ux-twig-component. En esencia, es una etiqueta Twig {{ include() }} más avanzada, que te permite pasar atributos HTML como class a los componentes. Una característica opcional que proporciona es esta sintaxis HTML. Si estás familiarizado con los componentes de frameworks frontales como Vue.js, ésta es básicamente la versión Twig. El paquete UX Icon se conecta a Twig Components y nos proporciona un práctico componente UX:Icon que podemos representar con <twig:ux:icon.... Eso puede hacer que nuestra plantilla sea más fácil de leer. Para saber más sobre los componentes Twig y todas las cosas interesantes que pueden hacer, busca "Symfony Twig Components" y consulta la documentación
A continuación: Empecemos a refactorizar nuestra aplicación para utilizar atributos de inyección de dependencia.
11 Comments
Very useful course!
Guys, please make DDD, CQRS and Event Driven Architecture courses. These courses are the base for the real development.
Thank you so much!
Hey Jared,
Thank you for your interest in SymfonyCasts tutorials! Yes, we have DDD topic in our idea pool, though I can't tell you when we may start working on it yet, too many good topics that need to be prioritized. But I counted your voice on that, as also on other topics :)
P.S. We have a Messenger course btw, you may want to look at it (if you haven't yet) https://symfonycasts.com/screencast/messenger
Cheers!
Yeah, the Messenger course is extensive! It covers all CQRS concepts well, so now I’m looking forward to the DDD course!
Hey Jared,
Awesome, glad to hear that Messenger course covers CQRS concepts for you well, thanks for confirming!
We're working on a Design Patterns complex v2 course right now, after that we will make some breaks with complex courses and revisit the DDD topic once again in a while to see if we can fit it into our schedule. Though not sure if that may happen this year fairly speaking, we still may prioritize some other "most wanted" topics.
Thanks for your understanding and patience! :)
Cheers!
Thank you so much for your response, Victor! I’m looking forward to it, no matter how much time it takes. Currently, I am watching the Messenger course, then I will move on to the Email course, and after that, I plan to switch to the design patterns. I'm really happy about the design pattern courses as well!
Great job! Best regards.
Hey Jared,
Good plan! Symfony Mailer has a nice integration with Messenger, so it should be a logical path to follow. Also, both design patterns courses are worth watching for a better understanding of how complex units work in frameworks. I would also recommend you to watch the SOLID course before design patterns if you haven't watched it yet. :)
Happy learning!
Cheers!
Thank you! I will definitely do that :)
I love how flexible and powerful DI is in Symfony. That's the real power!
No other framework has these possibilities. Great job and keep it up!
Could you please tell me how to properly understand the tutorials, just in other versions of symfony there are useful videos, but there are earlier versions, and if I work with version 7, how to understand whether the lesson will be relevant for me or not. Thank you in advance and thank you very much for your hard work, always looking forward to new courses).
Hey @Denis_Hello!
There are a couple ways to verify a course will be relevant for the current Symfony version you are using, let's assume Symfony 7:
That being said, it's probable that a course marked as Symfony 6 will still work with Symfony 7. There may be some things that don't work correctly (and we can help you in the comments if you come across this). The further back you go, for example, a Symfony 4 course, the more likely things won't work as shown in the video.
I hope that helps!
Kevin
Thank you very much for the answer) I will go to learn more, to learn this magical world of symfony)
"Houston: no signs of life"
Start the conversation!