The old site was based on php and there are lot of pages which are indexed, since we are keeping same urls in new wp sites but without .php extension at the end…
Assuming your “old site” .php
documents no longer exist (they shouldn’t) then your current rule block to remove the .php
extension would seem to be far more complex than it needs to be (and/or incorrect). (See below.)
the above mention code also remove .php from admin pages too.
Ok, something a bit odd here… Your existing rule block already excludes any URL that contains /wp-admin/
– so this should already exclude your admin pages. To also exclude wp-login.php
you could simply modify this same condition, although this would seem to be unnecessary (see below). wp-login.php
is not the only exception you need to make and adding many exceptions in this way quickly becomes impractical.
A quick assessment of your current rule block…
1. RewriteCond %{REQUEST_URI} !/wp-(content|admin|includes)/ [NC] 2. RewriteCond %{REQUEST_FILENAME} !-d 3. RewriteCond %{REQUEST_FILENAME}\.php !-f 4. RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/ 5. RewriteRule ^(.+)\.php$ $1 [R=301,L]
-
As noted above, this already excludes any URL that contains
/wp-content/
,/wp-admin/
or/wp-includes/
. However, assuming none of your old site URLs start withwp-
then why not simply exclude any URL that starts/wp-
– which naturally includeswp-login.php
,/wp-admin
, etc. There are potentially more than justwp-login
andwp-admin
URLs that need to be excluded here. -
Why do you need to check that the request does not map to a filesystem directory? Do you have directories that also end in
.php
?! Filesystem checks are relatively expensive and this condition looks superfluous. -
This check is not doing what (I think) you think it’s doing. The preceding comment states “the file does not exist” – that’s not what this condition does. If it did then you probably would not be asking your question. No part of this code checks that “the file does not exist”, which is really your main problem. If you request
/foo.php
then this condition checks that/foo.php.php
does not exist (which I’m sure it doesn’t), or if you request/foo/bar/baz.php
(where/foo/bar
does not exist as a physical directory) then it checks that/foo.php
does not exist – probably not the intention. -
The purpose of the check against
THE_REQUEST
server variable is to avoid a redirect loop – however, it can be simplified (the fragment identifier is never passed to the server, so#
is never matched). If your old URLs never contain a query string then it can be simplified further. But note that if your old URLs did/do contain a query string, then this will currently be passed onto the new target URL – is this the intention? -
This redirect only works because of the
RewriteBase
directive that is set later in the# BEGIN WordPress
section. Ideally, you would include the slash prefix on the substitution or include the canonical protocol + hostname (an absolute URL) and avoid a potential second redirect later.
Solution
Bringing the above points together, try something like the following instead (there is no need for the <IfModule mod_rewrite.c>
wrapper):
RewriteCond %{REQUEST_URI} !^/wp-
RewriteCond %{THE_REQUEST} "^GET /.+\.php(\?\S*)? HTTP/"
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(?!index\.php$)(.+)\.php$ /$1 [R=301,L]
Surrounding the CondPattern in quotes (ie. "
.."
) avoids the need to escape spaces in the regex.
\S
is a shorthand negated character class that matches any non-whitespace character. Similar to [^\ ]
as you had initially.
(?!index\.php$)
– This negative lookahead assertion in the RewriteRule
pattern ensures we don’t try to process the request after it has been rewritten to index.php
by the WP front-controller.
The filesystem check (really just a failsafe) is the last condition since this is the most “expensive”, so it’s only processed when the other conditions (and RewriteRule
pattern) are successful.
You will need to clear your browser cache before testing. Preferably test with 302 (temporary) redirects to avoid caching issues.