This is a simple technique which should work on ALL hosts to allow ExpressionEngine to handle URLs without index.php in them. Hopefully EllisLab will add this as a built-in option soon.
IJR
PATH_INFO, ORIG_PATH_INFO and REQUEST_URI do not work on common hosting provides such as DreamHost's VPS. So, we have to fall back to QUERY_STRING, but this causes more problems still.
The built in QUERY_STRING URI protocol blows away any query string values you may actually be using for important things like search form values, PayPal, or all kinds of other fun stuff. Use of these is a good idea when you need to, and is made easier by my colleague Brian Litzinger's awesome Module Super Globals: http://devot-ee.com/add-ons/super-globals/
So how do we fix this so that the query string survives? Basically all we have to do is pack the requested URI into a single query parameter named QSTR, and preserve the existing query string. Then make a small change to the core file URI.php to get it to use this new URI protocol. Finally, we set our config.php file's uri_protocol value to QUERY_PARAM and we're all set!
If you are using any extension which generates the & sign inside of a segment, this will not work very well - although neither would QUERY_STRING - so you're stuck anyway.
Here's how to apply this change to your site.
#### Do our rewrites
# Don't rewrite requests for real files or directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Match the entire query string value, this gets put into %1
RewriteCond %{QUERY_STRING} ^(.*)$
# Create a new redirect that packs the requested URI into QSTR and preserves the existing query string
RewriteRule ^(.*)$ index.php?QSTR=$1&%1 [L]
Use the new URI protocol that we're about to create.
$config['uri_protocol'] = 'QUERY_PARAM';
Find this block, and insert the // IRAWAY // section as shown:
if ($uri == 'REQUEST_URI')
{
$this->uri_string = $this->_parse_request_uri();
return;
}
// IRAWAY: add query param support
if ($uri == 'QUERY_PARAM' && isset($_GET['QSTR']))
{
$this->uri_string = $_GET['QSTR'];
return;
}
// END IRAWAY
$this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);