If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
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:
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
:
... 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
:
... 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.
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.
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
:
... 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: '.'
:
... 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.
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/Twig/blob/1.x/lib/Twig/Extension/Core.php#L102. 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!
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 %}
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!
Some mention of ways to programmatically control things like "Locale" here might be useful. eg The user is German so wants the "." thousand separator but the "," hundreds separator. ie per user configurations. A "mention" as I guess this is covered later in the course but would be nice to know here ;)
Hey Richie Hamburg!
I'm going to link this comment to our internal screencast ideas list. In short, I think you're right. But more broadly, we just haven't talked about translation or internationalization at all - it's sort of "out of the scope" of this tutorial, but not something that we actually cover anywhere. And this topic touches on a lot of things - date transformations in Twig, thousands separator in the form component, thousands separator in Twig's number_format, translations, etc. I think it could deserve its own attention!
Cheers!
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*", // v3.1.4
"doctrine/orm": "^2.5", // v2.7.2
"doctrine/doctrine-bundle": "^1.6", // 1.6.4
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
"symfony/swiftmailer-bundle": "^2.3", // v2.3.11
"symfony/monolog-bundle": "^2.8", // 2.11.1
"symfony/polyfill-apcu": "^1.0", // v1.2.0
"sensio/distribution-bundle": "^5.0", // v5.0.22
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.4" // 1.4.2
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.0.7
"symfony/phpunit-bridge": "^3.0" // v3.1.3
}
}
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?