This tutorial has a new version, check it out!

config_dev.yml & config_prod.yml

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.

Start your All-Access Pass
Buy just this tutorial for $12.00

We have two environments! That's super flexible... or I think it will be, just as soon as we figure out how the heck we can configure each environment.

Compare app.php and app_dev.php. What are the differences? Ok, ignore that big if block in app_dev.php. The important difference is a single line: the one that starts with $kernel = new AppKernel(). Hey, that's the class that lives in the app/ directory!

The first argument to AppKernel is prod in app.php:

33 lines web/app.php
... lines 1 - 22
$kernel = new AppKernel('prod', false);
... lines 24 - 33

And dev in app_dev.php:

33 lines web/app_dev.php
... lines 1 - 26
$kernel = new AppKernel('dev', true);
... lines 28 - 33

This defines your environment. The second argument - true or false - is a debug flag and basically controls whether or not errors should be shown. That's less important.

config_dev.yml versus config_prod.yml

Now, what do these dev and prod strings do? Here's the secret: when Symfony boots, it loads only one configuration file for the entire system. And no, it's not config.yml - I was lying to you. Sorry about that. No, the dev environment loads only config_dev.yml:

imports:
- { resource: config.yml }
framework:
router:
resource: "%kernel.root_dir%/config/routing_dev.yml"
strict_requirements: true
profiler: { only_exceptions: false }
web_profiler:
toolbar: true
intercept_redirects: false
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
bubble: false
verbosity_levels:
VERBOSITY_VERBOSE: INFO
VERBOSITY_VERY_VERBOSE: DEBUG
channels: ["!doctrine"]
console_very_verbose:
type: console
bubble: false
verbosity_levels:
VERBOSITY_VERBOSE: NOTICE
VERBOSITY_VERY_VERBOSE: NOTICE
VERBOSITY_DEBUG: DEBUG
channels: ["doctrine"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
# type: firephp
# level: info
#chromephp:
# type: chromephp
# level: info
#swiftmailer:
# delivery_address: me@example.com

And in prod, the only file it loads is config_prod.yml:

imports:
- { resource: config.yml }
#framework:
# validation:
# cache: validator.mapping.cache.apc
# serializer:
# cache: serializer.mapping.cache.apc
#doctrine:
# orm:
# metadata_cache_driver: apc
# result_cache_driver: apc
# query_cache_driver: apc
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console

Ok fellow deep sea explorers, this is where things get cool! Look at the first line of config_dev.yml:

imports:
- { resource: config.yml }
... lines 3 - 46

What does it do? It imports the main config.yml: the main shared configuration. Then, it overrides any configuration that's special for the dev environment.

Check this out! Under monolog - which is the bundle that gives us the logger service - it configures extra logging for the dev environment:

... lines 1 - 13
monolog:
handlers:
main:
... lines 17 - 18
level: debug
... lines 20 - 46

By setting level to debug, we're saying "log everything no matter its priority!"

So what about config_prod.yml? No surprise: it does the exact same thing: it loads the main config.yml file and then overrides things:

imports:
- { resource: config.yml }
... lines 3 - 28

This file has a similar setup for the logger, but now it says action_level: error:

... lines 1 - 15
monolog:
handlers:
main:
... line 19
action_level: error
... lines 21 - 28

This only logs messages that are at or above the error level. So only messages when things break.

Experimenting with config_dev.yml

Let's play around a bit with the dev environment! Under monolog, uncomment the firephp line:

... lines 1 - 13
monolog:
handlers:
... lines 16 - 34
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
firephp:
type: firephp
level: info
... lines 40 - 46

This is a cool handler that will show you log messages right in your browser.

Head over to it and run "Inspect Element". Make sure that the URL will access the dev environment and then refresh. And check this out: a bunch of messages telling us what route was matched. Heck, we can even see what route was matched for our ajax call. To see this working, you'll need a FirePHP extension installed in your browser. In your app, Monolog is attaching these messages to your response headers, and the extension is reading those. We don't want this to happen on production, so we only enabled this in the dev environment.

Environments are awesome! So how could we use them only cache our markdown string in the prod environment?

Leave a comment!

What PHP libraries does this tutorial use?

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