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 myapp_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/myapp/config/settings.yml

    no_script_name:  off

Now, the generated URLs will look like this:

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.

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.

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
  # comment the following 3 lines to allow periods in routes
  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]

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.

Tip To allow periods in your routes, simply comment the first two rewrite conditions and first rewrite rule in the .htaccess file.

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 SF_ROOT_DIR constants definition accordingly, and create the .htaccess URL rewriting configuration that you need for each application.