If you have a Laravel project, you might be surprised to find your routes are probably available on a number of different URLs.
Imagine the following example from your routes file:
<?php
Route::view('/feature/uptime-monitoring', 'front/feature/uptime-monitoring');
This creates a route at yourdomain.tld/feature/uptime-monitoring, which you’d expect.
But in most webserver configs, this means the following URLs are all valid and will all return an HTTP/1.1 200 OK with the same page:
https://ohdear.app/feature/uptime-monitoring
https://ohdear.app/index.php/feature/uptime-monitoring
What’s that index.php doing in there? It’s needed for some hosting environments that don’t support pretty-printed URLs.
But you might not need/want it, so let’s get rid of it!
Removing index.php from within your Laravel code#
One way to get rid of it, is to check the route in Laravel and issue a redirect there if needed.
Here’s one way to do this in app/Providers/RouteServiceProvider.php.
<?php
use Illuminate\Support\Str;
class RouteServiceProvider extends ServiceProvider
{
public function map(Router $router)
{
$this->removeIndexPhpFromUrl();
}
protected function removeIndexPhpFromUrl()
{
if (Str::contains(request()->getRequestUri(), '/index.php/')) {
$url = str_replace('index.php/', '', request()->getRequestUri());
if (strlen($url) > 0) {
header("Location: $url", true, 301);
exit;
}
}
}
}
This will redirect any URL with index.php in it.
$ curl -I "http://ohdear.app.test/index.php/pricing"
HTTP/1.1 301 Moved Permanently
Location: /pricing
$ curl -i "http://ohdear.app.test/index.php/feature/uptime-monitoring"
HTTP/1.1 301 Moved Permanently
Location: /feature/uptime-monitoring
There are some alternative ways to get the same result, by redirecting on the webserver itself.
Redirecting index.php in Nginx#
You can redirect if index.php is in the URL like this.
if ($request_uri ~* "^/index\.php(/?)(.*)") {
return 301 $2;
}
You might have to repeat this if you have different location {} blocks in your Nginx config.
Redirecting index.php in Apache#
You can add an additional line in your .htaccess.
$ cat .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirect if index.php is in the URL
RewriteRule ^index.php/(.+) /$1 [R=301,L]
</IfModule>
At least that’s an easy regex/fix. :-)
Redirecting index.php in Caddy#
It’s a bit cumbersome, but this seems to work in Caddy.
$ cat Caddyfile
https:// {
tls {
ask https://ohdear.app/caddy/allowed-domain
}
rewrite {
regexp ^/index.php/(.*)
to /{1}
}
redir {
if {uri} not {rewrite_uri}
/ {rewrite_uri}
}
}
It requires an internal rewrite to match the index.php and then a redir to redirect the actual request.