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 SubscribeWe know there's this container concept that holds all of our services... and we can see the full list of services by running:
php bin/console debug:container
Well, it turns out that the container holds one other thing: grudges. Seriously, don't expect to pull a prank on the service container and get away with it.
Ok, what it really holds, in addition to services, is parameters. These are simple configuration values, and we can see them by running a similar command:
php bin/console debug:container --parameters
These are basically variables that you can read and reference in your code. We don't need to worry about most of these, actually. They're set by internal things and used by internal things. But there are a few that start with kernel
that are pretty interesting, like kernel.project_dir
, which points to the directory of our project. Yep! If you ever need a way to refer to the directory of your app, this parameter can help.
So... how do we use these parameters? There are two ways. First, it's not super common, but you can fetch a parameter in your controller. For example, in VinylController
, let's dd($this->getParameter())
- which is a shortcut method from AbstractController
- and then kernel.project_dir
. We even get some nice auto-completion thanks to the Symfony PhpStorm plugin!
... lines 1 - 10 | |
class VinylController extends AbstractController | |
{ | |
... lines 13 - 31 | |
public function browse(MixRepository $mixRepository, string $slug = null): Response | |
{ | |
dd($this->getParameter('kernel.project_dir')); | |
... lines 35 - 42 | |
} | |
} |
And when we try it... yep! There it is!
Now... delete that. This works, but most of the time, the way you'll use parameters is by referencing them in your configuration files. And we've seen this before! Open up config/packages/twig.yaml
:
twig: | |
default_path: '%kernel.project_dir%/templates' | |
... lines 3 - 7 |
Remember that default_path
? That's referencing the kernel.project_dir
parameter. When you're in any of these .yaml
configuration files and you want to reference a parameter, you can use this special syntax: %
, the name of the parameter, then another %
.
Open up cache.yaml
. We're setting cache.adapter
to filesystem
for all environments. Then, we're overriding it to be the array
adapter in the dev environment only. Let's see if we can shorten this by creating a new parameter.
How do we create parameters? In any of these files, add a root key called parameters
. Below that, you can just... invent a name. I'll call it cache_adapter
, and set that to our value: cache.adapter.filesystem
:
parameters: | |
cache_adapter: 'cache.adapter.filesystem' | |
... lines 3 - 28 |
If you have a root framework
key, Symfony will pass all of the config to FrameworkBundle. The same is true with the twig
key and TwigBundle.
But parameters
is special: anything under this will create a parameter.
So yea... we now have a new cache.adapter
parameter... that we're not actually using yet. But we can already see it! Run:
php bin/console debug:container --parameters
Near the top... there it is - cache_adapter
! To use this, down here for app
, say %cache_adapter%
:
parameters: | |
cache_adapter: 'cache.adapter.filesystem' | |
... line 3 | |
framework: | |
cache: | |
... lines 6 - 13 | |
app: '%cache_adapter%' | |
... lines 15 - 28 |
That's it. Quick note: You may have noticed that sometimes I use quotes in YAML and sometimes I don't. Mostly, in YAML, you don't need to use quotes... but you always can. And if you're ever not sure if they're needed or not, better to be safe and use them.
Parameters are actually one example where quotes are required. If we didn't surround this with quotes, it would look like a special YAML syntax and throw an error.
Anyway, in the dev
environment, instead of saying framework
, cache
, and app
, all we need to do is override that parameter. I'll say parameters
, then cache_adapter
... and set it to cache.adapter.array
:
parameters: | |
cache_adapter: 'cache.adapter.filesystem' | |
... line 3 | |
framework: | |
cache: | |
... lines 6 - 13 | |
app: '%cache_adapter%' | |
... lines 15 - 23 | |
when@dev: | |
parameters: | |
cache_adapter: 'cache.adapter.array' |
To see if that's working, spin over here and run another helper command:
php bin/console debug:config framework cache
Remember, debug:config
will show you what your current configuration is under the framework
key, and then the cache
sub-key. And you can see here that app
is set to cache.adapter.array
- the resolved value for the parameter.
Let's check the value in the prod environment... just to make sure it's right there too. When you run any bin/console
command, that command will execute in the same environment your app is running in. So when we ran debug:config
, that ran in the dev environment.
To run the command in the prod environment, we could go over here and change APP_ENV
to prod
temporarily... but there's an easier way. You can override the environment when running any command by adding a flag at the end. For example:
php bin/console debug:config framework cache --env=prod
But before we try that, we always need to clear our cache first to see changes in the prod
environment. Do that by running:
php bin/console cache:clear --env=prod
Now try:
php bin/console debug:config framework cache --env=prod
And... beautiful! It shows cache.adapter.filesystem
. So, the container also holds parameters. This isn't a super important concept in Symfony, so, as long as you understand how they work, you're good.
Ok, let's turn back to dependency injection. We know that we can autowire services into the constructor of a service or into controller methods. But what if we need to pass something that's not autowireable? Like, what if we wanted to pass one of these parameters to a service? Let's find out how that works next.
Hey Jim,
Yeah, that config/packages/
folder is special and contains bundle-specific configs :) Try to put your config in just config/
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 config
directory I have put a file app.yaml
, which looks a bit like this:
app:
foo: bar
Then when I run debug:config app
I get the error described above. And when, in a console command, I have
$this->parameterBag->get('app.foo');
I get the error "You have requested a non-existent parameter "app.foo"".
Hey Jim-B,
Wait, if you drop that app.yaml
file from the config/packages/
and put into config/
- you should not have that No 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.yaml
and under parameters:
key add your data. Then you will be able to fetch those parameters with the code you showed in the end :)
Cheers!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"knplabs/knp-time-bundle": "^1.18", // v1.19.0
"symfony/asset": "6.1.*", // v6.1.0-RC1
"symfony/console": "6.1.*", // v6.1.0-RC1
"symfony/dotenv": "6.1.*", // v6.1.0-RC1
"symfony/flex": "^2", // v2.1.8
"symfony/framework-bundle": "6.1.*", // v6.1.0-RC1
"symfony/http-client": "6.1.*", // v6.1.0-RC1
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/runtime": "6.1.*", // v6.1.0-RC1
"symfony/twig-bundle": "6.1.*", // v6.1.0-RC1
"symfony/ux-turbo": "^2.0", // v2.1.1
"symfony/webpack-encore-bundle": "^1.13", // v1.14.1
"symfony/yaml": "6.1.*", // v6.1.0-RC1
"twig/extra-bundle": "^2.12|^3.0", // v3.4.0
"twig/twig": "^2.12|^3.0" // v3.4.0
},
"require-dev": {
"symfony/debug-bundle": "6.1.*", // v6.1.0-RC1
"symfony/maker-bundle": "^1.41", // v1.42.0
"symfony/stopwatch": "6.1.*", // v6.1.0-RC1
"symfony/web-profiler-bundle": "6.1.*" // v6.1.0-RC1
}
}
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.php
file in theconfig
folder 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.yaml
file inconfig/packages
but when I rundebug:config app
it says "No extensions with configuration available for "app"".