Buy

Config.yml: Control Center for Services

Ok, I get it: I bring in a bundle and it gives me more useful objects. But, there must be a way for us to configure and control how these services behave, right? Otherwise, how could we control what server the mailer uses for sending emails? Or what if we want to change how the logger works: making it log to a database instead of the default var/logs/dev.log file?

The answer to all of this lies in just one file: app/config/config.yml. That's right: one file is responsible for controlling everything from the log file to the database password. That's pretty powerful: so let's find out how it works!

Other than imports - which loads other files - and parameters - which we'll talk about soon - every root key in this file - like framework, twig and doctrine - corresponds to a bundle that is being configured:

72 lines app/config/config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
framework:
... lines 12 - 35
# Twig Configuration
twig:
... lines 38 - 42
# Doctrine Configuration
doctrine:
... lines 45 - 72

All of this stuff under framework is configuration for the FrameworkBundle:

72 lines app/config/config.yml
... lines 1 - 10
framework:
#esi: ~
#translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: ~
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
fragments: ~
http_method_override: true
assets: ~
... lines 35 - 72

Everything under twig is used to control the behavior of the services from TwigBundle:

72 lines app/config/config.yml
... lines 1 - 35
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
... lines 40 - 72

The job of a bundle is to give us services. And this is our chance to tweak how those services behave.

Get a big List of all Configuration

That's amazing! Except... how are we supposed to know what keys can live under each of these sections? Documentation of course! There's a great reference section on symfony.com that shows you everything you can control for each bundle.

But I'll show you an even cooler way.

Head back to terminal and use our favorite ./bin/console to run config:dump-reference:

./bin/console config:dump-reference

Actually, there's a shorter version of this called debug:config. This shows us a map with the bundle name on the left and the "extension alias" on the right... that's a fancy way of saying the root config key.

Tip

You can also use the shorter: ./bin/console debug:config command.

That's not really that useful. But re-run it with an argument: twig:

./bin/console config:dump-reference twig

Woh! It dumped a giant yml example of everything you can configure under the twig key. Ok, it's not all documented... but honestly, this is usually enough to find what you need.

Playing with Configuration

Ok, lets's experiment! Obviously, the render() function we use in the controller leverages a twig service behind the scenes. Pretend that the number of known species is this big 99999 number and send that through a built-in filter called number_format:

40 lines app/Resources/views/genus/show.html.twig
... lines 1 - 4
{% block body %}
<h2 class="genus-name">{{ name }}</h2>
<div class="sea-creature-container">
<div class="genus-photo"></div>
<div class="genus-details">
<dl class="genus-details-list">
... lines 12 - 14
<dd>{{ '99999'|number_format }}</dd>
... lines 16 - 17
</dl>
</div>
</div>
<div id="js-notes-wrapper"></div>
{% endblock %}
... lines 23 - 40

Refresh! That filter gives us a nice, 99,999, formatted-string. But what if we lived in a country that formats using a . instead? Time to panic!!?? Of course not: the bundle that gives us the twig service probably gives us a way to control this behavior.

How? In the config:dump-reference dump, there's a number_format:, thousands_separator key. In config.yml, add number_format: then thousands_separator: '.':

72 lines app/config/config.yml
... lines 1 - 35
# Twig Configuration
twig:
... lines 38 - 39
number_format:
thousands_separator: '.'
... lines 42 - 72

Behind the scenes, this changes how the service behaves. And when we refresh, that filter gives us 99.999.

If this makes sense, you'll be able to control virtually every behavior of any service in Symfony. And since everything is done with a service... well, that makes you pretty dangerous.

Now, what if you make a typo in this file? Does it just ignore your config? Hmm, try it out: rename this key to thousand_separators with an extra s. Refresh! Boom! A huge error! All of the configuration is validated: if you make a typo, Symfony has your back.

Leave a comment!

  • 2016-08-25 Victor Bocharsky

    Hey Christophe,

    Well, that's probably OK so long as you know that variable's content comes from your code, but not from user input. Otherwise, you need to think about filtering user input. You could do it by yourself, for example create a custom twig filter which will do filtering and mark output safe for html which allows to you do not use raw filter in templates. Or use some third-party filtering library. The most popular is ezyang/htmlpurifier. BTW, you could check an example of its implementation for markdown service in symfony-demo project.

    Cheers!

  • 2016-08-25 Christophe Lablancherie

    Hi,
    I've used the raw "format" but when i try to validate my code on insight, it's said to me that there are some problems with XSS, and that's right because we doesn't used "escape code"... So what's the good way ?

    We don't have to use this :

    {% autoescape %}
    {{ funFact | raw }}
    {% endautoescape %}

  • 2016-04-24 weaverryan

    Hi Daniel!

    Ah, that's a great question. For the most part, these values cannot be changed at runtime. The reason is that they're read statically ONE time (when you deploy) and used to write out all the configuration for how to instantiate the services. If you want to change something at run-time, it won't be done via config.yml. Instead, you'll need to look into the specific library that you're using (e.g. Twig) and see how you might change the setting you want at runtime. This doesn't come up very often, and whether or not something is easy just depends on the situation.

    In this particular situation, the setting is passed to the `Twig_Extension_Core` class: https://github.com/twigphp/Twi.... To set this at run-time, you would need to fetch this off of the twig service and set it. From a controller:


    $this->container->get('twig')
    ->getExtension('core') // core is the getName() from that Core.php file
    ->setNumberFormat(2, ',', '.');

    Cheers!

  • 2016-04-21 Daniel Noyola

    is there a way to change/set this variable through code in a determined class like the controller? For example, let's say that I want to do a multilingual app/site and I want to change the number_format variable based in the current user language, How I could achieve something like that?