Using mod_rewrite to hide .php from the end of URL

2019-02-13 16:24发布

问题:

I've got a site where all the pages are php scripts, so the URLs end .php.

I've added the following to a .htaccess file, and I can now access the .php files without the .php extension:

RewriteEngine On  # Turn on rewriting

RewriteCond %{REQUEST_FILENAME}.php -f  # If the requested file with .php on the end exists
RewriteRule ^(.*)$ $1.php #  serve the PHP file

So far so good. But now I want to add a Redirect on all the .php files so that any old links outside of my control get redirected to the new version of the URL.

I've tried this:

RewriteEngine On  # Turn on rewriting

RewriteCond %{REQUEST_URI} .*\.php
RewriteRule ^(.*)\.php$ http://example.com/$1 [R=permanent,L]

RewriteCond %{REQUEST_FILENAME}.php -f  # If the requested file with .php on the end exists
RewriteRule ^(.*)$ $1.php [L] #  serve the PHP file

but that seems to send a redirect even for URLs that don't end in .php, so I get stuck in an infinite loop. Any other combination I try seems to match no requests (and leave me at page.php) or all requests (and get me stuck in a loop).

回答1:

RewriteEngine On

RewriteCond %{THE_REQUEST} ^\w+\ /(.*)\.php(\?.*)?\ HTTP/
RewriteRule ^ http://%{HTTP_HOST}/%1 [R=301]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .* $0.php

Only %{THE_REQUEST} is not rewritten in the internal redirection that happens in the second rule (%{REQUEST_URI}, on the other hand, is).



回答2:

You redirecting pages ending with .php to the page without .php

Then your first rule rewites all pages not ending with .php to the page name ending with .php

This is why you have a loop :-)



回答3:

You might be able to also add [L] to the RewriteRule for adding .php, so that it stops processing the other Rules:

RewriteRule ^(.*)$ $1.php [L] #  serve the PHP file


回答4:

Add NS to parameters list of that last rule



回答5:

Thanks to a pointer to this question by @TheDeadMedic, I was able to find a solution to my own problem by changing:

RewriteCond %{REQUEST_URI} .*\.php

to:

RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP

I don't understand why my version didn't do the same thing, though.