Modern PHP frameworks like Laravel, Symfony, and CodeIgniter all implement a front controller pattern where all HTTP requests are routed through a single entry point (typically index.php). This approach enables clean URLs and centralized request handling.
Here's the most effective way to implement this using Apache's mod_rewrite:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [QSA,L]
For those using Nginx, the equivalent configuration would be:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
Your index.php file should then process the request URI:
The error message you encountered ("Invalid URI in request") typically occurs when:
- The .htaccess file isn't in the correct directory
- Apache's AllowOverride isn't set to All
- There are syntax errors in the rewrite rules
Here's a more sophisticated router implementation:
routes[$pattern] = $handler;
}
public function dispatch() {
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
foreach ($this->routes as $pattern => $handler) {
if (preg_match("#^$pattern$#", $uri, $matches)) {
array_shift($matches);
return call_user_func_array($handler, $matches);
}
}
http_response_code(404);
echo '404 Not Found';
}
}
$router = new Router();
$router->addRoute('/products/(\d+)', function($id) {
echo "Showing product $id";
});
$router->dispatch();
While the front controller pattern is powerful, consider these optimizations:
- Cache .htaccess rules using RewriteMap for high-traffic sites
- Implement opcode caching (OPcache) for PHP
- Use a compiled router like FastRoute for better performance
When building modern PHP applications - especially MVC frameworks - we often need all requests to be processed by a single entry point (typically index.php) while maintaining clean, SEO-friendly URLs. The challenge is configuring the web server to handle this routing properly.
The solution primarily involves Apache's mod_rewrite module. Here's the most effective .htaccess configuration I've found after extensive testing:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
This:
1. Checks if the requested file doesn't exist (!-f)
2. Checks if the requested directory doesn't exist (!-d)
3. Routes everything to index.php while preserving query strings (QSA) and making this the last rule (L)
Based on the original question's error logs, two key issues emerged:
[error] [client 127.0.0.1] Invalid URI in request GET / HTTP/1.1
[error] [client 127.0.0.1] Invalid URI in request GET /abc HTTP/1.1
Apache Version Differences
# For Apache 2.2.4 (older versions)
RewriteRule ^(.*)$ /index.php [QSA,L]
# For Apache 2.2.11+ (modern versions)
RewriteRule ^(.*)$ index.php [QSA,L]
The leading slash requirement was removed in later versions. Always test with your specific Apache version.
Here's a full working example that demonstrates URL routing:
For production applications, consider these enhancements:
# Handle trailing slashes consistently
RewriteCond %{REQUEST_URI} ^(.+)/$
RewriteRule ^ %1 [R=301,L]
# Exclude common static files from rewriting
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif|ico)$ [NC]
Most PHP frameworks like Laravel and Symfony use similar principles but with more sophisticated routers. Here's how they typically structure their .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/index\.php [NC,OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^ index.php [L]