If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeQuestion: if config.yml
is so important - then what the heck is the point of all of these other files - like config_dev.yml
, config_test.yml
, parameters.yml
, security.yml
and services.yml
. What is their purpose?
The answer is environments. Now, I don't mean environments like dev
, staging
, or production
on your servers. In Symfony, an environment is a set of configuration. Environments are also one of its most powerful features.
Think about it: an application is a big collection of code. But to get that code running it needs configuration. It needs to know what your database password is, what file your logger should write to, and at what priority of messages it should bother logging.
Symfony has two environments by default: dev
and prod
. In the dev
environment your code is booted with a lot of logging and debugging tools. But in the prod
environment, that same code is booted with minimal logging and other configuration that makes everything fast.
Tip
Actually, there's a third environment called test
that you might use while writing
automated tests.
So.... how do we choose which environment we're using? And what environment have we been using so far?
The answer to that lives in the web
directory, which is the document root. This is the only directory whose files can be accessed publicly.
These two files - app.php
and app_dev.php
- are the keys. When you visit your app, you're always executing one of these files. Since we're using the server:run
built-in web server: we're executing app_dev.php
:
... lines 1 - 2 | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\Debug\Debug; | |
// If you don't want to setup permissions the proper way, just uncomment the following PHP line | |
// read http://symfony.com/doc/current/book/installation.html#checking-symfony-application-configuration-and-setup | |
// for more information | |
//umask(0000); | |
// This check prevents access to debug front controllers that are deployed by accident to production servers. | |
// Feel free to remove this, extend it, or make something more sophisticated. | |
if (isset($_SERVER['HTTP_CLIENT_IP']) | |
|| isset($_SERVER['HTTP_X_FORWARDED_FOR']) | |
|| !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server') | |
) { | |
header('HTTP/1.0 403 Forbidden'); | |
exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.'); | |
} | |
/** | |
* @var Composer\Autoload\ClassLoader $loader | |
*/ | |
$loader = require __DIR__.'/../app/autoload.php'; | |
Debug::enable(); | |
$kernel = new AppKernel('dev', true); | |
$kernel->loadClassCache(); | |
$request = Request::createFromGlobals(); | |
$response = $kernel->handle($request); | |
$response->send(); | |
$kernel->terminate($request, $response); |
The web server is preconfigured to hit this file.
That means that when we go to localhost:8000/genus/octopus
that's equivalent to going to localhost:8000/app_dev.php/genus/octopus
. With that URL, the page still loads exactly like before.
So how can we switch to the prod
environment? Just copy that URL and change app_dev.php
to app.php
. Welcome to the prod
environment: same app, but no web debug toolbar or other dev tools:
... lines 1 - 2 | |
use Symfony\Component\HttpFoundation\Request; | |
/** | |
* @var Composer\Autoload\ClassLoader | |
*/ | |
$loader = require __DIR__.'/../app/autoload.php'; | |
include_once __DIR__.'/../var/bootstrap.php.cache'; | |
// Enable APC for autoloading to improve performance. | |
// You should change the ApcClassLoader first argument to a unique prefix | |
// in order to prevent cache key conflicts with other applications | |
// also using APC. | |
/* | |
$apcLoader = new Symfony\Component\ClassLoader\ApcClassLoader(sha1(__FILE__), $loader); | |
$loader->unregister(); | |
$apcLoader->register(true); | |
*/ | |
//require_once __DIR__.'/../app/AppCache.php'; | |
$kernel = new AppKernel('prod', false); | |
$kernel->loadClassCache(); | |
//$kernel = new AppCache($kernel); | |
// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter | |
//Request::enableHttpMethodParameterOverride(); | |
$request = Request::createFromGlobals(); | |
$response = $kernel->handle($request); | |
$response->send(); | |
$kernel->terminate($request, $response); |
This baby is optimized for speed.
But don't worry: in production you won't have this ugly app.php
in your URL: you'll configure your web server to execute that file when nothing appears in the URL.
So this is how you "choose" your environment. And other than on your production server, you'll pretty much always want to be in the dev
environment.
But the real fun starts next: when we learn how to bend and optimize each environment exactly to our needs.
Hey Marko!
Hmmm. So first, let's try to figure out if the 404 is coming from Symfony (meaning Symfony is running, but it is not finding any route) or if it's coming from somewhere else (e.g. Nginx, because it can't find/execute app.php). If the error looks something like this - https://samsonasik.files.wo... - that *is* coming from Symfony... and for some reason, there is no route found. Let me know, this would indeed be weird, since you have already thought of clearing the cache :). If the error looks different, it might be some other issue.
Cheers!
Hi Ryan, sorry for forgetting to include that piece of info, the 404 is actually coming from nginx. Thanks for the quick response! :)
Hey Marko,
Hm, could you double check your virtual host configuration? Is your document root path is valid? Does it point to web/ directory of your Symfony project? Do you have app.php file in this web/ folder? See https://symfony.com/doc/cur... for more instructions for Nginx web server.
Btw, when you do not specify app.php in the URL it works? I mean, both URLs: http://your-domain.example.... and http://your-domain.example.... does not work for you or only the 2nd one?
Cheers!
Hi Victor,
yes, the document root is /web, and app.php file exists. The official Symfony docs states that the only thing that needs to be added to the Homestead.yaml is type: symfony
http://symfony.com/doc/curr...
and this is my configuration in the Homestead.yaml file
folders:
- map: C:/Users/marko/code
to: /home/vagrant/code
type: "nfs"
sites:
- map: symfony.app
to: /home/vagrant/code/aqua_note/web
type: symfony
Yes, it only doesn't work with app.php in the URL, but if I put app_dev.php or leave it out completely, everything works normal.
Here's the sites' nginx configuration from Homestead
https://pastebin.com/gt61mNsb
Thanks!
Hey Marko,
Ah, that's easy win - just comment out "internal;" line, it prevents calling /app.php directly... which is exactly what you want in production btw, so I'd not recommend you allowing it :)
P.S. I haven't used Homestead, so don't know whether there an option for that in their config file.
Cheers!
Hey!
When I change the URL from app_dev.php to app.php I get an error :O
The server returned a "500 Internal Server Error".
Well, with app_dev.php I have no problems but this app.php thing might be problematic issue in the future.
Do you know maybe what is making this error in the prod environment?
cheers!
Hey Claudio!
This is actually totally normal :). And we talk a bit more about why a few chapters from now: https://knpuniversity.com/s...
Basically, when you use the "prod" environment (app.php), Symfony does not rebuild any of its cached files. That means that if you edited a route and used app.php, Symfony would try to use the old (cached) route configuration. Often, you've made *so* many changes to configuration, that when you use app.php, the cache is so outdated that it causes the application to error out like this. But, like I said, that's totally normal: you will always clear your cache (bin/console cache:clear --env=prod) before switching to the prod environment. This becomes part of your deploy process: move the files to your server, then clear the prod cache. When you clear the cache, you won't have any errors :).
But, btw, if you *do* ever have a 500 Internal Server Error in the future (these can happen on production if you have a bug in your code!) you can see the error information by looking at your var/logs/prod.log file.
Cheers!
And it seems I jumped the gun and replied to your other comment before I saw this one ;). No harm done - it'll help others I'm sure!
// 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
}
}
Hi, does anyone have any idea why accessing the prod link (with app.php, not app_dev.php) returns a 404?
I'm using Homestead VM on Windows instead of serving the app locally. Tried with bin/console cache:clear --env=prod already, but it doesn't make any difference.