Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Bundle Config (to Control Bundle Services)

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We're now using the HttpClientInterface and CacheInterface services. Yay! But we aren't actually responsible for instantiating these service objects. Nope, they're created by something else (we'll talk about that in a few minutes), and then just passed to us.

That's great because all of these services - the "tools" of our app - come ready to use, out-of-the-box. But... if something else is responsible for instantiating these service objects, how can we control them?

Introducing: bundle configuration!

Bundle Configuration

Go check out the config/packages/ directory. This has a number of different YAML files, all of which are loaded automatically by Symfony when it first boots up. These files all have exactly one purpose: to configure the services that each bundle gives us.

Open up twig.yaml:

twig:
default_path: '%kernel.project_dir%/templates'
when@test:
twig:
strict_variables: true

For now, ignore this when@test: we're going to talk about that in a few minutes. This file has a root key called twig. And so, the entire purpose of this file is to control the services provide by the "Twig" bundle. And, it's not the filename - twig.yaml - that's important. I could rename this to pineapple_pizza.yaml and it would work exactly the same and be delicious. I don't care what you think.

When Symfony loads this file, it sees this root key - twig - and says:

Oh, okay. I'm going to pass whatever configuration is below to TwigBundle.

And remember! Bundles give us services. Thanks to this config, when TwigBundle is preparing its services, Symfony passes it this configuration and TwigBundle uses it to decide how its services should be instantiated... like what class names to use for each service... or what first second or third constructor arguments to pass.

For example, if we changed the default_path to something like %kernel.project_dir%/views, the result is that the Twig service that renders templates would now be pre-configured to look in that directory.

The point is: the config in these files give us the power to control the services that each bundle provides.

Let's check out another one: framework.yaml:

# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
http_method_override: false
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
cookie_samesite: lax
storage_factory_id: session.storage.factory.native
#esi: true
#fragments: true
php_errors:
log: true
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file

Because the root key is framework, all of this config is passed to FrameworkBundle... which uses it to configure the services it provides.

And, as I mentioned, the filename doesn't matter... though the name often matches the root key... just for sanity reasons: like framework and framework.yaml. But that's not always the case. Open up cache.yaml:

framework:
cache:
# Unique name of your app: used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null

Woh! This is... just more config for FrameworkBundle! It lives in its own file... just because it's nice to have a separate file to control the cache.

Debugging the Available Bundle Config

At this point, you might be asking yourself:

Ok, cool... but what config keys are we allowed to put here? Where can I find which options are available?

Great question! Because... you can't just "invent" whatever keys you want: that would throw an error. First, yes, you can, of course, read the documentation. But there's another way: and it's one of my favorite things about Symfony's config system.

If you want to know what configuration you can pass to "Twig" bundle, there are two bin/console commands to help you. The first is:

php bin/console debug:config twig

This will print out all of the current configuration under the twig key, including any default values that the bundle is adding. You can see our default_path set to the templates/ directory, which comes from our config file. This %kernel.project_dir% is just a fancy way to point to the root of our project. More on that later.

Try this: change the value to views, re-run that command and... yup! We see "views" in the output. Let me go ahead and change that back.

So debug:config shows us all of the actual, current config for a specific bundle, like twig... which is especially handy since it also shows you defaults added by the bundle. It's a great way to see what you can configure. For example, apparently we can add a global variable to Twig via this globals key!

The second command is similar: Instead of debug:config, it's config:dump:

php bin/console config:dump twig

debug:config shows you the current configuration... but config:dump shows you a giant tree of example configuration, which includes everything that's possible. Here you can see globals with some examples of how you could use that key. This is a great way to see every potential option that you can pass to a bundle... to help it configure its services.

Let's use this new knowledge to see if we can "teach" the cache service to store its files somewhere else. That's next.

Leave a comment!

2
Login or Register to join the conversation
BYT Avatar
BYT Avatar BYT | posted 6 months ago | edited

I want to keep the controller, templates, forms, css and js all in one folder to organize them together in one folder because they are easy to find. When there are thousands of them and spread out across different folder then it's not easy to find them all work on. How can I have that setup? The common templates could stay in the default templates folder.

Reply

Hey BYT,

That will be difficult to achieve because as templates everything in Symfony should be in its specific directory. Form types in src/, CSS and JS files - in assets/, Twig templates - in the templates/ dir, etc. So, I would recommend you to keep everything in its own place.. but use a specific naming. For example, if you have a form named RegistrationForm.php - you can related files in next folders:

  • src/Form/RegistrationForm.php
  • templates/form/registration.html.twig
  • assets/form/registration.js
  • assets/form/registration.css

So as you can see, every file named "registration" and I suppose you will be able to find related files very easily. Or, alternatively, you can name folders instead of files, something like:

  • assets/registration/form.js
  • assets/registration/form.css
  • etc.

I hope this helps!

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// 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
    }
}
userVoice