Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
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

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

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!

47
Login or Register to join the conversation
Default user avatar
Default user avatar Jeroen Noten | posted 4 years ago

I struggled with making the firephp logging getting to work in Chrome as well, and I managed to found the solution:
1. instead of uncommenting the firephp config section, uncomment the chromephp config section
2. install the 'Chrome Logger' extension and enable it by clicking the black icon in the top right.

I hope this helps others!

3 Reply
Patryk W. Avatar
Patryk W. Avatar Patryk W. | Jeroen Noten | posted 4 years ago | edited

Thanks Jeroen Noten. Really good tip :)

3 Reply

Thanks for sharing Jeroen Noten!

1 Reply
Ahmed C. Avatar

thanks but it does not show anything for me

Reply
Gianluca T. Avatar

thanks

Reply
Default user avatar

Is it necessarily for the future tutorials\lessons Fire PHP or it just for this lesson to see messages are coming?

Reply

Hey, Ilya!

It's not required for other screencasts, just a usage example for this chapter. But feel free to use this if it helps you, of course.

Reply
Default user avatar

Thanks, Victor
Becouse I've got some troubles earlier whith PHP Storm (I didn't install PHP Annotation plugin.)

Reply

Hey, Ilya!

Have you installed PHP Annotation plugin already? Can I help you with installation?

Reply
Default user avatar

Hey
No, it's ok. Thank you

Reply
Default user avatar
Default user avatar Richie Hamburg | posted 4 years ago

Can you point to where and how monolog is used to add those headers you mention above please.

Reply

Hey Richie Hamburg
Who actually does the job of adding those headers is the extension FirePHP or ChromePHP (symfony has support for both) you need to install it and then enable it in the config.yml file as shown in the video

After enabling it, you can use monolog as always, accesing it through container or injecting into a service


$logger = $this->get('logger');
$logger->info('I just got the logger');
$logger->error('An error occurred');

You can read more about monolog here:
http://symfony.com/doc/curr...

Have a nice day!

Reply
Default user avatar
Default user avatar Krzysztof | posted 4 years ago

I read all comments below, but logging is not working for me.
I'm using Chrome, so I've uncommented this:

chromephp:
type: chromephp
level: info

I installed and launched Chrome Logger. Then I launched aquanote website, I hit Inspect element, I clicked on the first element (octopus) but I'm getting only these Response headers:

Cache-Control:no-cache, private
Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8
Date:Wed, 25 Oct 2017 09:39:25 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.25 (Win32) OpenSSL/1.0.2j PHP/7.1.2
Transfer-Encoding:chunked
X-Debug-Token:7358a3
X-Debug-Token-Link:http://aquanote.sy/_profile...
X-Powered-By:PHP/7.1.2

The last header from this: https://imgur.com/0d85kfK is missing.

Nothing is appearing in console too. What am I doing wrong?

Reply

Hey Krzysztof

That's a bit weird, make sure you are accessing to the dev enviroment. If you already are, I believe your chrome extension have a problem, or maybe clearing the cache might help `php bin/console cache:clear`

Cheers!

Reply
Default user avatar
Default user avatar Sofyann Fahim | posted 4 years ago

Hello, I have a problem, when I'm in prod (with app.php in my URL) the query is still displayed, is it normal?

Thanks for helps !

Reply

Hey Sofyann,

Id be glad to help you, but what query are you talking about?

Cheers!

Reply
Default user avatar
Default user avatar Sofyann Fahim | victor | posted 4 years ago

Hey,
I have the request in the console when i'm in prod. In the video it says (if I understand correctly) that normally this is displayed only in dev mode. I'm talking about the "request > Object ....."

Sorry, my english is bad so I use google translate ^^'

Thanks you !

Reply

Hey Sofyann Fahim
Did you enable "firephp" for the prod environment? If so just disable it and clear cache

Cheers!

Reply
Default user avatar
Default user avatar Sofyann Fahim | MolloKhan | posted 4 years ago

Hi,
I have :
# firephp:
# type: firephp
# level: info
chromephp:
type: chromephp
level: info

in config_dev.yml but not in config_prod.yml so I do not understand why this is displayed when I'm in prod mode (with app.php)

In the config_prod i have just :

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
process_psr_3_messages: false

Thanks for your help !

Reply

Hmm, can you undo your changes to that file, clear cache and try again?
Oh, and can you show me what's been shown?

Cheers!

Reply
Default user avatar
Default user avatar Sofyann Fahim | MolloKhan | posted 4 years ago

Cancel my changes in this file? That is, comment on chromephp?

request : {message: "Matched route "genus_show_notes".", context: {…}}
context: {route: "genus_show_notes", route_parameters: {…}, request_uri: "http://localhost:8000/genus/octopus/notes", method: "GET"}message: "Matched route "genus_show_notes"."__proto__: Object

Reply

> Cancel my changes in this file? That is, comment on chromephp?
Yes.
Hmm, I believe you have that configuration in your main file, i.e. config.yml file. If that's the case, just remove it from it

Reply
Default user avatar
Default user avatar Sofyann Fahim | MolloKhan | posted 4 years ago

When I comment, the request is not displayed, but the problem is that when it is enabled, it has to work only in dev mode no? I have nothing about monolog in config.yml ... My code is the same as in the course. The problem is not very serious because I just have to comment on chromephp when I deploy the site but it's just to understand the reason ...

Reply

Did you just say that when you comment the configuration in your config_dev.yml, it affects your production environment? If so, check your "web/app.php" file, you may changed the environment

Reply
Default user avatar
Default user avatar Sofyann Fahim | MolloKhan | posted 4 years ago

Ceci se produit uniquement avec chromephp. J'ai voulu vérifier si les deux fichiers étaient bien chargé dans leurs environnement approprié avec :

(config_prod)
twig:
number_format:
thousands_separator: '..'

--------------------------------------
(config_dev)
twig:
number_format:
thousands_separator: ';'

The goal was to see if the difference was taken into account and yes, it worked. So I do not understand why when I activate chromephp in config_dev it is also active in config_prod (in app.php). Maybe it comes from the AJAX code?

I'm really sorry for my English ... I know it must not be easy to read. So thank you so much

Reply

Hmm, this is getting interesting :)
It could that your AJAX is hitting a production path, but only if you hardcoded it
Try "copy and paste" the config_prod.yml file from our finish folder (when you download the course code)
Then clear the production cache, like this


bin/console cache:clear -e prod
Reply
Default user avatar
Default user avatar Sofyann Fahim | MolloKhan | posted 4 years ago

I tried what you told me. The only difference : i have in my config_prod : process_psr_3_messages: false in "monolog >>> console" more. But the problem persists, I'm really sorry I did not find the solution quickly enough :(

Reply
Default user avatar

:o ! I noticed something!
In the console i have:
XHR loading: GET "http://localhost:8000/genus/octopus/notes".
And: http://localhost:8000/genus/octopus/notes
is exactly the same in production and in dev. It does not display the "app.php" or "app_dev.php" even if I put it in the URL of my browser. Maybe that's the reason? If so ... I do not understand why it does not take into account the URL I put in my browser?

Reply

That's weird, maybe you have some custom .htaccess rules configured?
What happens when you hit in your browser "http://localhost:8000/app_dev.php/genus/octopus/notes" (hitting app_dev.php)
Is it possible to upload your project to github or wherever you want? So I can download and check it deeper

Reply
Default user avatar
Default user avatar Sofyann Fahim | MolloKhan | posted 4 years ago

Sorry i don't know for the .htaccess ... I follow all the step in the course. When i hit http://localhost:8000/app_dev.php/genus/octopus/notes i have the JSON response.
The github : https://github.com/sofyann/... (but I advanced in the course)

Reply

Hey Sofyann Fahim ,

Hm, I start getting lost in those comments :) Do you use a real web server like Apache or Nginx? Or do you use built-in PHP web server and running it with a Symfony command like "bin/console server:run"? Because I just bootstrapped your project locally and it works fine for me. When I go to the http://localhost:8000/app.php/genus/octopus - I do not see any logs in Google Chrome's Console tab. But as far as I load this page in dev mode, i.e. call http://localhost:8000/app_dev.php/genus/octopus - I start seeing logs in Google Chrome's Console tab, and those logs are from Chrome Logger extension. And as I understand it's exactly how it *should* work. Do you have a different behavior?

But, there's an odd case when I load the page in dev mode at first and only then switch to the prod mode - I still see logs, but that's because Chrome Logger extension loaded them from my previous session. I mean, it's the logs from dev mode, if you look closer you won't see any new logs every second in prod mode. Well, that's a feature of this extension, and why it works so - the question to its developer :) But if you reload page again with Cmd + R (or Ctrl + R for Windows users) - you won't see any logs in prod mode at all :)

I guess, it's just some kind of caching or maybe some safe way to avoid get lost those logs if you accidentally reload the page - so asI said it's just a feature of this extension. But but but, you do receive any new logs in prod environment, at least I don't notice any new logs on your project :)

I hope this answers your question.

Cheers!

1 Reply
Default user avatar
Default user avatar Sofyann Fahim | victor | posted 4 years ago

Hello, thank you for your answer !
I fix the problem (maybe you have loaded my code after).
I think it was the note.react.js file. in
loadNotesFromServer: function () {
$ .ajax ({
url: '/ genus / octopus / notes',
success: function (data) {
this.setState ({notes: data.notes});
} .bind (this)
});

The url is "hardcoded", so I downloaded a new source code into the courses a little further and the url in the function was: this.props.url
I do not know ReactJS but I think the problem came from there? Because now everything is ok :)

I apologize for not updating my question earlier! And I thank you infinitely for your patience :)

Reply

Ohh, that's why you were hitting a route in prod environment, when you were in dev environment. Nice catch!

Cheers!

Reply
Default user avatar
Default user avatar Rich Wilx | posted 4 years ago

I'm sitting here still, watching these vids. And, with every step forward, I'm just thinking "Symfony is <expletive> brilliant!"
The developers have done an awesome job.

And "by Poseidon's beard" your videos are great: Well scripted, no muffled voices, no noisy keyboard presses.

Reply

Hey Rich,

Haha, thank you for this excellent feedback and all the kind words in our direction!

Cheers!

Reply
Default user avatar
Default user avatar Andrew Grudin | posted 4 years ago

I have installed FirePHP extension in my Chrome but don't see any message telling me what route was matched when inspecting element on localhost:8000/genus/octopus (((

Reply

Hey Andrew!

Did you also make the change in config_dev.yml to activate this on the Symfony side? One other way to check (to see if things are configured correctly on the Symfony side) is to open your inspect, refresh, then find the request for the full page that just finished. In the first tab, you can see the "response" headers. There should be a BUNCH of weird response headers - like this: http://i.imgur.com/0d85kfK.png. If you can see that, you're setup on the Symfony side - but something isn't right with the extension.

Cheers!

Reply
Default user avatar
Default user avatar Andrew Grudin | weaverryan | posted 4 years ago

I have installed FirePHP4Chrome and it is working ... The fact is FirePHP for Chrome doesn't work (which was installed first by me).

I see now in Inspect: request Object {message: "Matched route "genus_show_notes".", context: Object}

Just one thing, I can't find in my Inspect something like request you are talking about... and line ( Headers Preview Response Cookies Timing ) as in your http://i.imgur.com/0d85kfK.png.
Where should I look that stuff for?
Best regards!

Reply

If it's working, don't worry about those headers. But if you're curious, open the "inspect element" on your browser (Chrome), click the network tab and then refresh. You should see a bunch of requests in this list, for the main page, CSS files etc. Select the first one (for the main page) and you should see something like what I've shown: these are the response headers sent back by Symfony. The headers are how Symfony communicates with the browser plugin :)

-1 Reply
Default user avatar
Default user avatar Andrew Grudin | weaverryan | posted 4 years ago

I catch it , thanks for your time and invaluable help!

Reply
Default user avatar
Default user avatar Juan Nicolás | posted 4 years ago

Hello, I did everything and it works, I installed ChromePHP and I enabled it, but it does not show me the path name: http://imgur.com/a/jsjqz

What I did wrong? Thanks!

Reply

Hey Juan!

> but it does not show me the path name

Are you referring to this message in the console: "XHR finished loading: GET "http://localhost:8000/app_dev.php/genus/octopus/notes"?

If so, *this* actually doesn't come from the logger :). It's a browser setting to show AJAX requests (XHR requests) in the console. You can enable it by right-clicking on the console and selecting "Log XMLHtttpRequests": http://imgur.com/3rp0sTc

But if you're referring to something else, let me know!

Cheers!

Reply
Default user avatar
Default user avatar Richie Hamburg | posted 4 years ago

No logging here either. 100% using the _dev environment (with and without the app_dev.php) and nothing is appearing in the chrome console. tried two different firePHPs and also ChromePHP just to be sure. 100% uncommented the firephp paragraph in config_dev.yml too. Suggestions?

Reply

Hey Richie!

Hmm..... So, here's how this works. When you activate the firephp handler in Monolog (there is also a chromephp handler - you could try that instead), it ultimately triggers this class (and its base class): https://github.com/symfony/.... Specifically, the onKernelResponse() method is called. As you can see, this looks to see if the Request has some headers in it. Basically, it's checking to make sure that the plugin is installed in your browser: when the plugin is installed, it should add a header to the request to "advertise" itself. If that header is not present, then the firephp handler does nothing. I would look in the Network tools in your browser to see what the Request headers are of your main request! You could also temporarily add some debugging code to this function to see if Symfony sees that header.

If Symfony is doing its job, then you should be able to see an extra header on your Response (again, look in the network tools). It will look something like this: http://i.imgur.com/0d85kfK.png. If you see this, Symfony is doing its job! But for some reason, your plugin is not picking it up. If you do NOT see this, Symfony is not doing its job, either because something is misconfigured, or because your plugin isn't sending the necessary header to "advertise" its presence.

Phew! I hope that at least gives you some ideas for debugging! Some of these plugins are better maintained than others, which could be part of the problem!

Let me know what you find out!

1 Reply
Default user avatar
Default user avatar Richie Hamburg | weaverryan | posted 4 years ago

The magic of computers - I have my error logs now - uninstalling and reinstalling the extension seems to have triggered it. But I'm not seeing headers in the network tab of chrome tools for some reason. Maybe I'm being blind - it's a long day. http://imgur.com/KYSDWQi

Reply
Default user avatar

Aha. All sorted. Thanks.

Reply

Hey Richie!

Ha! Of course that would be the solution :). About the headers, they might be there - you're just not quite looking in the correct spot. In the network tab (which is what your screenshot is looking at) scroll all the way to the top of the list. The first item on the list will be the request for this actual page - will be something like /genus/octopus. Click on that item. That should open up a big section on the right with a bunch of tabs: Headers, Preview, Response, etc. It'll look like my screenshot: http://i.imgur.com/0d85kfK.png. Make sure you're on the Headers tab, then scroll down to where you see the "Response Headers". Check for the header there.

tl;dr; The response headers don't show up on the full list of requests - but just click on one of the individual requests to see them! You should also see the headers if you click on any of the AJAX requests (i.e. any of the "notes" rows in the network list).

Cheers!

Reply
Cat in space

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

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