Front-Controller Routing

Front-Controller Routing for a PHP Application

A front controller sends every request that is not a real file to one script, which reads the original path from REQUEST_URI. Laravel 2,157 and WordPress 48 work this way (WordPress Front Controller, Laravel):

A front controller in .htaccessApache config
# /var/www/example/.htaccess: every URL that is not a file goes to index.php
# Needs: mod_rewrite; AllowOverride FileInfo; Options FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]

Lines 4 and 5 let CSS, images and directories through; line 6 rewrites the rest to index.php relative to this directory, so the file also works in a subfolder. The rewrite is internal, so the method, query string and POST body reach PHP intact:

/var/www/example/index.php, a minimal routerPHP
<?php
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$routes = ['#^/$#' => fn() => 'home page', '#^/products/(\d+)$#' => fn($id) => "product $id"];
foreach ($routes as $pattern => $handler) {
    if (preg_match($pattern, $path, $m)) {
        exit($handler(...array_slice($m, 1)) . " (via {$_SERVER['SCRIPT_NAME']})\n");
    }
}
http_response_code(404);
echo "no route for $path\n";
Output
/                      home page (via /index.php)  [200]
/products/42?ref=mail  product 42 (via /index.php)  [200]
/css/site.css          body{}  [200]
/nope                  no route for /nope  [404]
/old.php               no route for /old.php  [404]

mod_dir's one-line alternative, FallbackResource /index.php, belongs to the Indexes class: under AllowOverride FileInfo it returned 500 with FallbackResource not allowed here. With FileInfo Indexes it routed the first four URLs alike, but for /old.php PHP's handler claimed the missing file and Apache 129 's own 404 page came back. Use the rewrite when old .php links must reach the router.