1. Removing the "index.php" Part From URLs

You need mod_rewrite for Apache or something similar for other web servers, such as ISAPI_Rewrite for Microsoft IIS to get rid of the "index.php" part in incoming and generated URLs.

1.1. Apache with mod_rewrite

Make sure mod_rewrite is enabled and the required AllowOverride settings are active, and rename dist.htaccess to .htaccess in your pub directory which has the the following contents:

# rename this file to .htaccess to remove the necessity to have index.php in front of routes
# make sure mod_rewrite is on and AllowOverride settings are okay

# these two aren't really necessary
DirectoryIndex index.php
Options -MultiViews -Indexes

<IfDefine APACHE2>
AcceptPathInfo On
</IfDefine>

<IfModule mod_rewrite.c>
# enable rewrite engine
RewriteEngine Off

# ********** THIS IS THE ONLY SETTING YOU SHOULD HAVE TO CHANGE **********
RewriteBase /WEBSERVER/PATH/TO/pub/
# e.g. RewriteBase /~dzuelke/_projects/agavi/trunk/samples/pub/
# usually just "/" if your application's pub dir is the document root

# if requested url does not exist (i.e. it's likely an agavi route), pass it as path info to index.php
RewriteRule ^$ index.php?/ [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?/$1 [QSA,L]
</IfModule>

All you must do is enable rewriting:

RewriteEngine On

and change the rewrite base to point to your pub directory URL path:

RewriteBase /~cbrown/projects/win-a-baseball-match/pub/

The important thing is that you use the external path to the pub directory as the RewriteBase, i.e. the path that you would have to enter in your web browser location bar to reach the index page - in our example, the project is located at /~cbrown/projects/win-a-baseball-match/. If the pub directory is the document root, then the RewriteBase is just /.

The RewriteCond is a condition that executes the following RewriteRule if the requested filename (that is the incoming URL already mapped to a filesystem name by Apache) does not exist. If the requested URL exists, for instance, when an image on the webserver is requested, Agavi won't be called. Otherwise, the framework is started and the given URL is handed to Agavi as so-called Path Info which the WebRouting will use to match a route.

Tip

Of course you can also use the rewrite rules in your virtual host configuration. However, keep the following things in mind when doing that:

  1. You cannot use a RewriteBase, so you have to use the full relative path in the rewrite rules and destinations, including the leading slash.

  2. The RewriteCond on %{REQUEST_FILENAME} only work if the request filename has the full document root prepended to it, i.e. %{DOCUMENT_ROOT}%{REQUEST_FILENAME}

Assuming your application is in the webserver root, i.e. called via "/" from the outside, that would mean:

RewriteRule ^/$ /index.php?/ [QSA,L]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php?/$1 [QSA,L]

1.2. LightTPD

In your lighttpd.conf, add the following lines (this example assumes that our project is in /~cbrown/projects/win-a-baseball-match/):

url.rewrite-once = ( 
  "^/~cbrown/projects/win-a-baseball-match/pub/([^?]*)(?:\?(.*))?$" => "/~cbrown/projects/win-a-baseball-match/pub/index.php?/$1&$2"
)

While the pattern looks a bit ugly-ish, it is strongly recommended that you don't use your own in order for the routing to work reliably. Don't worry, it's been engineered by a German, it won't let you down.

Restart Lighty, and everything should work.

However, we're not there yet. The pattern works and does it's job, but unfortunately, it's a bit overzealus and will rewrite any URL. That's not exactly what we want, because our images, stylesheets and other static files must remain accessible. So we have to add another rewrite that catches URLs that shouldn't be rewritten, in our case any that begins on "modpub", "img", "css" or "files":

url.rewrite-once = ( 
  "^/~cbrown/projects/win-a-baseball-match/pub/(modpub|img|css|files).*" => "$0", 
  "^/~cbrown/projects/win-a-baseball-match/pub/([^?]*)(?:\?(.*))?$" => "/~cbrown/projects/win-a-baseball-match/pub/index.php?/$1&$2"
)

Don't forget to restart Lighty again for the changes to take effect.

1.3. Microsoft IIS with ISAPI_Rewrite

This example assumes you're using the Lite version of ISAPI_Rewrite, which does not allow per-directory htaccess.ini files - all rewrite rules have to be put into the httpd.ini in the directory where ISAPI_Rewrite was installed. For now, we use these rules (assuming your project is sitting in /users/cbrown/projects/win-a-baseball-match/):

UriMatchPrefix /users/cbrown/projects/win-a-baseball-match/pub/
UriFormatPrefix /users/cbrown/projects/win-a-baseball-match/pub/
RewriteRule ([^?]*)(?:\?(.*))? index.php?/$1&$2 [L]

While the pattern looks a bit ugly-ish, it is strongly recommended that you don't use your own in order for the routing to work reliably. Don't worry, it's been engineered by a German, it won't let you down.

Restart IIS, and everything should work.

However, we're not there yet. The pattern works and does it's job, but unfortunately, it's a bit overzealus and will rewrite any URL. That's not exactly what we want, because our images, stylesheets and other static files must remain accessible. So we have to add a rewrite condition that prevents rewriting for URLs that shouldn't be rewritten, in our case any that begins on "modpub", "img", "css" or "files":

UriMatchPrefix /users/cbrown/projects/win-a-baseball-match/pub/
UriFormatPrefix /users/cbrown/projects/win-a-baseball-match/pub/
RewriteCond URL (?!modpub|img|css|files).*
RewriteRule ([^?]*)(?:\?(.*))? index.php?/$1&$2 [L]

Don't forget to restart IIS again for the settings to take effect (unless you'd like to wait until ISAPI_Rewrite figures out something has changed, but that will take up to an hour).