views:

63

answers:

5

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).

A: 

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 :-)

Pete
I've rewritten the question with my .htaccess file in full. The rule that adds the .php comes after the one that removes it and redirects. AFAICS, something is wrong with the RewriteCond
rjmunro
A: 

Add NS to parameters list of that last rule

Col. Shrapnel
I thought that would work too, but it doesn't seem to work. Additionally, for the condition `RewriteCond %{IS_SUBREQ} =false`, I get `[localhost/sid#1fd6de0][rid#5aa2e20/initial/redir#1] (4) [perdir U:/htdocs/] RewriteCond: input='false' pattern='=false' => matched`
Artefacto
That didn't work for me.
rjmunro
A: 

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
gnarf
I tried this and it made no difference. I've added it to the version in the question to save ambiguity.
rjmunro
A: 

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.

rjmunro
See my answer. Your solution is only slightly different (only works for GET requests).
Artefacto
+1  A: 
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).

Artefacto