Before getting deeper into the routing system, one matter needs to be clarified. In the examples given in the previous section, there is no mention of the front controller (index.php
or frontend_dev.php
) in the internal URIs. The front controller, not the elements of the application, decides the environment. So all the links must be environment-independent, and the front controller name can never appear in internal URIs.
There is no script name in the examples of generated URLs either. This is because generated URLs don't contain any script name in the production environment by default. The no_script_name
parameter of the settings.yml
file precisely controls the appearance of the front controller name in generated URLs. Set it to off
, as shown in Listing 9-5, and the URLs output by the link helpers will mention the front controller script name in every link.
Listing 9-5 - Showing the Front Controller Name in URLs, in apps/frontend/config/settings.yml
prod:
.settings
no_script_name: off
Now, the generated URLs will look like this:
http://www.example.com/index.php/articles/finance/2006/activity-breakdown.html
In all environments except the production one, the no_script_name
parameter is set to off
by default. So when you browse your application in the development environment, for instance, the front controller name always appears in the URLs.
http://www.example.com/frontend_dev.php/articles/finance/2006/activity-breakdown.html
In production, the no_script_name
is set to on
, so the URLs show only the routing information and are more user-friendly. No technical information appears.
http://www.example.com/articles/finance/2006/activity-breakdown.html
But how does the application know which front controller script to call? This is where URL rewriting comes in. The web server can be configured to call a given script when there is none in the URL.
In Apache, this is possible once you have the mod_rewrite
extension activated. Every symfony project comes with an .htaccess
file, which adds mod_rewrite
settings to your server configuration for the web/
directory. The default content of this file is shown in Listing 9-6.
Listing 9-6 - Default Rewriting Rules for Apache, in myproject/web/.htaccess
<IfModule mod_rewrite.c> RewriteEngine On # we skip all files with .something RewriteCond %{REQUEST_URI} \..+$ RewriteCond %{REQUEST_URI} !\.html$ RewriteRule .* - [L] # we check if the .html version is here (caching) RewriteRule ^$ index.html [QSA] RewriteRule ^([^.]+)$ $1.html [QSA] RewriteCond %{REQUEST_FILENAME} !-f # no, so we redirect to our front web controller RewriteRule ^(.*)$ index.php [QSA,L] </IfModule>
The web server inspects the shape of the URLs it receives. If the URL does not contain a suffix and if there is no cached version of the page available (Chapter 12 covers caching), then the request is handed to index.php
.
However, the web/
directory of a symfony project is shared among all the applications and environments of the project. It means that there is usually more than one front controller in the web directory. For instance, a project having a frontend
and a backend
application, and a dev
and prod
environment, contains four front controller scripts in the web/
directory:
index.php // frontend in prod frontend_dev.php // frontend in dev backend.php // backend in prod backend_dev.php // backend in dev
The mod_rewrite settings can specify only one default script name. If you set no_script_name to on for all the applications and environments, all URLs will be interpreted as requests to the frontend
application in the prod
environment. This is why you can have only one application with one environment taking advantage of the URL rewriting for a given project.
Tip There is a way to have more than one application with no script name. Just create subdirectories in the web root, and move the front controllers inside them. Change the path to the ProjectConfiguration
file accordingly, and create the .htaccess
URL rewriting configuration that you need for each application.