I\'m currently hiding the .php extension from the urls on my nginx server with this configuration:
location / {
try_files $uri $uri/ @extensionless-php;
i
To redirect those requests permanently with HTTP 301 code try
rewrite ^(.*)\.php$ $1 permanent;
Put this directive before your location
blocks.
Update
After this being answered, OP asked another question (now being deleted) - what if you have the following webroot structure:
webroot
|
+-- index.php (PHP file)
|
+-- somename.php (PHP file)
|
+-- somename (folder)
| |
| +-- index.php (PHP file)
|
+-- someothername (folder)
|
+-- index.php (PHP file)
Previous solution makes it impossible to serve somename.php
file, because the request to http://example.com/somename
would be redirected by try_files
directive to http://example.com/somename/
and in next turn would be served with somename/index.php
file.
This can be solved, but you'll have to stop using index
and try_files
directives and emulate their behavior with your own request processing logic. This is what I've ended up with:
map $original_uri $maybe_slash {
~/$ '';
default '/';
}
server {
...
if ($original_uri = '') {
set $original_uri $uri;
}
# redirect requests of '/somepath/somefile.php' to '/somepath/somefile'
rewrite ^(.*)\.php$ $1 pemanent;
location / {
# this emulates 'try_files $uri $uri/ ...' directive behavior and redirects '/some/path'
# to '/some/path/' if 'some/path.php' file does not exists, but 'some/path' folder exists
# and there are 'some/path/index.html' file in that folder
set $check_redirect $rewrited$maybe_slash;
if ( $check_redirect = '1/' ) {
return 301 $original_uri/$is_args$args;
}
if ( -f $document_root$uri.php ) { rewrite ^ $uri.php last; }
# this emulates 'index index.php index.html' directive behavior
if ( -f $document_root$uri${maybe_slash}index.php ) {
set $rewrited 1;
rewrite ^ $uri${maybe_slash}index.php last;
}
if ( -f $document_root$uri${maybe_slash}index.html ) {
set $rewrited 1;
rewrite ^ $uri${maybe_slash}index.html last;
}
# if a request for an absent resource should be served with some backend
# controller, it is ok to use some 'try_files' directive here like
# try_files $uri /index.php?path=$original_uri;
}
location ~ \.php$ {
# this emulates 'try_files $uri $uri/ ...' directive behavior and redirects '/some/path'
# to '/some/path/' if 'some/path.php' file does not exists, but 'some/path' folder exists
# and there are 'some/path/index.php' file in that folder
set $check_redirect $rewrited$maybe_slash;
if ( $check_redirect = '1/' ) {
return 301 $original_uri/$is_args$args;
}
# no 'try_files $uri =404' or 'include snippets/fastcgi-php.conf' here, this location
# can be reached only if requested PHP file is really exists in webroot folder
include fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root$uri;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
}
With this configuration and webroot structure given above
http://example.com/
would be served with webroot/index.php
file;http://example.com/somename
would be served with webroot/somename.php
file;http://example.com/somename.php
would be redirected to http://example.com/somename
and served with webroot/somename.php
file;http://example.com/somename/
would be served with webroot/somename/index.php
file;http://example.com/someothername
would be redirected to http://example.com/someothername/
(since no webroot/someothername.php
file exists) and served with webroot/someothername/index.php
file.Important note about custom HTTP error pages
If you have some custom error page, for example webroot/error/404.php
for HTTP 404 error, instead of usual way to define it like
error_page 404 /error/404.php;
you'd need to skip .php
extension of that file:
error_page 404 /error/404;