Nice urls with symfony
Symfony | Technical | Development | July 15, 2010
Usually when working with symfony, when the time comes to deploy the application, one problem arises, the urls.
While developing a normal url could be: http://www.jnieto.org/web/index.php/articles/my_first_article
Two elements are not welcome here: index.php and web/
Index.php/
To get rid of index.php a setting must be configure in the settings.yml file from the config folder:
prod:
.settings:
no_script_name: true
Now after cleaning the cache the annoying index.php is gone.
Note: Just an application can have this setting as true (more info in this regard in the symfony guide )
Web/
This can be avoided depending on the kind of hosting available. If it is a dedicated server then the solution is to change the webroot to be the actual web dir. Ok that's the easy one, however when using a shared hosting some steps should be followed.
First add to the factories.yml file of the desire application the following code:
controller:
class: FrontWebController
Then create the class FrontWebController.class.php in the project/lib/controller folder (it could be other folder but this follows the symfony original folder structure).
The class should overwrite the method genUrl:
public function genUrl($parameters = array(), $absolute = false) { $url = parent::genUrl($parameters, $absolute); if(preg_match('/\.php/', $url) || preg_match('/index\.php/', $_SERVER['SCRIPT_NAME'])) $url = substr($url, 0, strpos($url, 'web')). substr($url, strpos($url, 'web') + 4); return $url; }
This method helps the link_to's to generate urls without the usual .../web/...
Don't forget to clean the cache for symfony to take account of the changes.
Now copy the .htaccess file to the root folder and copy this code:
Options +FollowSymLinks +ExecCGI
RewriteEngine On
# we skip all files in /web
RewriteCond %{REQUEST_URI} ^/web/
RewriteRule .* - [L]
# we rewrite all other files with .something to /web
RewriteCond %{REQUEST_URI} \..+$
RewriteCond %{REQUEST_URI} !\.html$
RewriteRule ^(.*)$ /web/$1 [L]
# we check if the .html version is in /web (caching)
RewriteRule ^$ /web/index.html [QSA]
RewriteRule ^([^.]+)$ /web/$1.html [QSA]
#####################################################
# no, so we redirect to our front web controller
RewriteRule ^(.*)$ /web/index.php [QSA,L]
This code gets rid of the undesired web/, now the site could be accessed by:
http://www.jnieto.org/articles/my_first_article
A nice and clean url.
References:
http://forum.symfony-project.org/index.php/m/102500/#msg_102500
http://groups.google.com/group/symfony-devs/browse_thread/thread/0ec9a54b46725beb?pli=1
In facts, the web root must link to the /web directory, not the root of the symfony project.
If you have a URL like http://host/web/xxx, then some of your data are exposed (e.g. http://host/config/*.yml).