Parámetros
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeSabemos que existe este concepto de contenedor que contiene todos nuestros servicios... y podemos ver la lista completa de servicios ejecutando
php bin/console debug:container
Listado de Parámetros
Pues bien, resulta que el contenedor guarda otra cosa: rencores. En serio, no esperes gastar una broma al contenedor de servicios y salirte con la tuya.
Vale, lo que realmente guarda, además de los servicios, son parámetros. Son simples valores de configuración, y podemos verlos ejecutando un comando similar:
php bin/console debug:container --parameters
Son básicamente variables que puedes leer y referenciar en tu código. En realidad, no tenemos que preocuparnos por la mayoría de ellos. Son establecidas por cosas internas y utilizadas por cosas internas. Pero hay algunas que empiezan por kernelque son bastante interesantes, como kernel.project_dir, que apunta al directorio de nuestro proyecto. ¡Sí! Si alguna vez necesitas una forma de referirte al directorio de tu aplicación, este parámetro puede ayudarte.
Obtención de parámetros de un controlador
Entonces... ¿cómo utilizamos estos parámetros? Hay dos maneras. En primer lugar, no es muy común, pero puedes obtener un parámetro en tu controlador. Por ejemplo, en VinylController, vamos a dd($this->getParameter()) -que es un método abreviado de AbstractController - y luego a kernel.project_dir. ¡Incluso obtenemos un bonito autocompletado gracias al plugin Symfony PhpStorm! Y cuando lo probamos... ¡sí! ¡Ahí está!
Haciendo referencia a los parámetros con %parameter%
Ahora... borra eso. Esto funciona, pero la mayoría de las veces, la forma en que utilizarás los parámetros es haciendo referencia a ellos en tus archivos de configuración. Y esto ya lo hemos visto antes! Abre config/packages/twig.yaml. ¿Recuerdas ese default_path? Eso es hacer referencia al parámetro kernel.project_dir. Cuando estés en cualquiera de estos archivos de configuración de .yamly quieras hacer referencia a un parámetro, puedes utilizar esta sintaxis especial: %, el nombre del parámetro, y luego otro %.
Crear un nuevo parámetro
Abre cache.yaml. Vamos a configurar cache.adapter como filesystem para todos los entornos. Luego, lo anulamos para que sea el adaptador array sólo en el entorno dev. Veamos si podemos acortar esto creando un nuevo parámetro.
¿Cómo se crean los parámetros? En cualquiera de estos archivos, añade una clave raíz llamadaparameters. Debajo de ella, puedes simplemente... inventar un nombre. Lo llamaré cache_adapter, y ponle nuestro valor: cache.adapter.filesystem.
Si tienes una clave raíz framework, Symfony pasará toda la configuración a FrameworkBundle. Lo mismo ocurre con la clave twig y TwigBundle.
Pero parameters es especial: todo lo que esté por debajo de ella creará un parámetro.
Así que sí... ahora tenemos un nuevo parámetro cache.adapter... que en realidad aún no estamos utilizando. ¡Pero ya podemos verlo! Ejecuta:
php bin/console debug:container --parameters
Cerca de la parte superior... ahí está - ¡ cache_adapter! Para utilizarlo, aquí abajo para app, di %cache_adapter%.
Eso es todo. Nota rápida: Te habrás dado cuenta de que a veces utilizo comillas en YAML y a veces no. La mayoría de las veces, en YAML, no es necesario utilizar las comillas... pero siempre se puede. Y si alguna vez no estás seguro de si son necesarias o no, mejor estar seguro y utilizarlas.
Los parámetros son, de hecho, un ejemplo en el que las comillas son necesarias. Si no lo rodeáramos con comillas, parecería una sintaxis especial de YAML y arrojaría un error.
De todos modos, en el entorno dev, en lugar de decir framework, cache, y app, lo único que tenemos que hacer es anular ese parámetro. Diré parameters, luegocache_adapter... y lo pondré en cache.adapter.array.
Para ver si eso funciona, gira aquí y ejecuta otro comando de ayuda:
php bin/console debug:config framework cache
Recuerda que debug:config te mostrará cuál es tu configuración actual bajo la claveframework, y luego la subclave cache. Y aquí puedes ver que app está configurado como cache.adapter.array, el valor resuelto para el parámetro.
Comprobemos el valor en el entorno prod... sólo para asegurarnos de que también es correcto. Cuando ejecutes cualquier comando de bin/console, ese comando se ejecutará en el mismo entorno en el que se esté ejecutando tu aplicación. Así que cuando ejecutamos debug:config, eso se ejecuta en el entorno dev.
Para ejecutar el comando en el entorno prod, podríamos ir aquí y cambiarAPP_ENV por prod temporalmente... pero hay una forma más fácil. Puedes anular el entorno al ejecutar cualquier comando añadiendo una bandera al final. Por ejemplo:
php bin/console debug:config framework cache --env=prod
Pero antes de intentarlo, siempre tenemos que borrar nuestra caché primero para ver los cambios en el entorno prod. Hazlo ejecutando:
php bin/console cache:clear --env=prod
Ahora prueba:
php bin/console debug:config framework cache --env=prod
Y... ¡qué bien! Aparece cache.adapter.filesystem. Así pues, el contenedor también contiene parámetros. Este no es un concepto súper importante en Symfony, así que, mientras entiendas cómo funcionan, estás bien.
Bien, volvamos a la inyección de dependencias. Sabemos que podemos autoinyectar servicios en el constructor de un servicio o en los métodos del controlador. ¿Pero qué pasa si necesitamos pasar algo que no es autoconectable? Por ejemplo, ¿qué pasa si queremos pasar uno de estos parámetros a un servicio? Averigüemos cómo funciona eso a continuación.
8 Comments
Previously, we saw that yaml configurations in a file are parsed in the order the declared.
Regarding parameters, this seems like an exception to this.
Regarding cache, when framework.cache.app is parsed, you would expect it to contain the previously declared cache_adapter parameter, which is not environment aware, and then when it is overridden in when@dev, that this would have no effect, because cache.app is already declared.
Isn't this a bit confusing?
Hey Alkiviadis,
Not sure I completely understand you here, but you're probably overthinking about it. First of all, in the dev env when we're changing a config file - the cache will be automatically recompiled so any new changes you made in the config will be re-parsed on the next request. In prod Symfony mode it's a bit different, when you change a config file - you will need to clear the cache manually to let the system notice your changes. So, in both cases the cache will be re-compiled and so the new parameter values will be used.
I hope this helps.
Cheers!
Thank you for your answer, but I am actually talking about the order the configurations are read, not when and if the cache is cleared.
Specifically while on (
cache.yaml) we had in the middle of course:even when we are at dev environment, framework.cache.app already got assigned a value from the first cache_adapter declaration, before the cache_adapter parameter got reassigned with new value later. But the framework.cache.app got the final value of cache_adapter, which seemed strange to me at first.
So, are all parameters parsed/set first, and then anything else?
Hey Alkiviadis,
It's important do understand that Symfony first gathers all the configuration from separate config files and only then trying to resolve parameter values. Actually, the parameter values will be resolved even later only when you fetch the service from the service container - the container will instantiate the service object and resolve all the parameter values it has.
Yeah, it probably might be confusing at first sight, but that's just an overwritten operation. Yes, when the config file is parsed - the
framework.cache.appwill be set to the%cache_adapter%(but it's just instructions, it's still not resolved actual value yet). And later if you're in adevmode, thewhen@devwill be parsed as well which will overwrite the values that were already set before (if any).If it's confusing you - you can avoid
when@devsyntax and put the dev config inside theconfig/packages/devfolder, but behind the scene it will work the same anyway: it first will gather all the default config (for all environments), and only then overwrite any whiles with env-specific config.So, even though it's an overwriting operation in some cases - that's actually really powerful and flexible: you have the default config values but can overwrite some values with other ones for specific enviroments.
I hope this clarifies things!
Cheers!
Coming from Laravel, I'm a bit confused where I can put general config for my app. In Laravel I could just create a
MyApp.phpfile in theconfigfolder and then read it from wherever. So say I have some project-wide config in my Symfony app, where should I put it? I tried creating aapp.yamlfile inconfig/packagesbut when I rundebug:config appit says "No extensions with configuration available for "app"".Hey Jim,
Yeah, that
config/packages/folder is special and contains bundle-specific configs :) Try to put your config in justconfig/dir, it should work well this way :)Cheers!
Thanks for the reply Victor. Unfortunately I still get the same error, also after clearing the cache. So in the
configdirectory I have put a fileapp.yaml, which looks a bit like this:Then when I run
debug:config appI get the error described above. And when, in a console command, I haveI get the error "You have requested a non-existent parameter "app.foo"".
Hey Jim-B,
Wait, if you drop that
app.yamlfile from theconfig/packages/and put intoconfig/- you should not have thatNo extensions with configuration available for "app"error anymore, as nobody will parse your file at all. And this means you would need to parse that file yourself.But in your second example I see you just want to add some data to the config so that system knows about your data. If so, you need to add "parameters" - that's how it's called in Symfony. For this, you can open
config/services.yamland underparameters:key add your data. Then you will be able to fetch those parameters with the code you showed in the end :)Cheers!
"Houston: no signs of life"
Start the conversation!