RewriteCond %{REQUEST_FILENAME} !^/PhP/?$
RewriteCond %{REQUEST_FILENAME} !^/forms/?$
RewriteCond %{REQUEST_URI} !^/PhP/?$
RewriteCond %{REQUEST_URI} !^/forms/?$
You don't need to check against both REQUEST_FILENAME
and REQUEST_URI
- you're just repeating the same check. It's easier to use REQUEST_URI
(the URL-path) in this instance.
The REQUEST_FILENAME
server variable contains the absolute filesystem path (not the URL-path) that the request maps to, so will never start with /PhP/
or /forms/
anyway - so the these two conditions will always be successful.
However, the second two conditions that check against REQUEST_URI
are only checking the directory itself - because of the trailing end-of-string anchor ($
) on the regex - this is not excluding the "connect & config files*1 within those directories". (Presumably /PhP.php
and /forms.php
don't exist anyway, so your last condition is already excluding these requests anyway.)
(*1 Although you wouldn't expect "connect & config" files to require being accessible over HTTP anyway??)
You also need to include these same "exceptions" on the first rule that redirects requests for .php
to remove the extension.
Try the following instead:
# 1. Remove ".php" extension (external redirect)
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule !^(PhP|forms) %1 [R,L]
# 2. Internal rewrite to append the ".php" extension
RewriteCond %{REQUEST_URI} !^/(PhP|forms)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
Note that I've combined the two (short) directories into a single condition using regex alternation. If you want to exclude many directories then it may be easier to read/maintain if you have multiple conditions.
On the first "redirect", we can include the exception directly in the RewriteRule
pattern, since this is not being used in the substitution string (unlike the later rewrite). This is more efficient, as the RewriteRule
pattern is processed first (before the preceding conditions). Note that the URL-path matched by the RewriteRule
pattern does not start with a slash (unlike the value of the REQUEST_URI
server variable, which contains the full URL-path, including the slash prefix).
The CondPattern !^/(PhP|forms)
simply checks that the requested URL-path does not start with /PhP
or /forms
- we don't need to include the trailing slash here (unless you also had files named /PhP.php
or /forms.php
in the document root - but I assume not, since the later condition that checks !-d
would already block these requests from being rewritten).
Aside:
RewriteRule ^(.*?)/?$ $1.php [L]
You are currently allowing an optional trailing slash on your URLs. I would settle on one or the other, not both (from an SEO perspective). You are presumably consistent in your URL structure and only linking to one or the other (and including a rel="canonical"
in your pages), so really that is the only version you need to check for in your directives.
The URL with and without the trailing slash are two different URLs - yet you are serving the same content for both. Strictly speaking this is potentially duplicate content.
UPDATE: Your initial redirect (that removes the .php
extension from old URLs) actually redirects to the URL without a trailing slash - so I would assume this is the desired option.
what would be the expression which does NOT include the slash?
Ordinarily you would just assume there is no slash on the end of the URL (the rewrite will fail*2 if there is), so the directive is simplified to:
RewriteRule (.*) $1.php [L]
If you specifically wanted to avoid matching any URL that includes a trailing slash (so nothing happens, ie. a 404 will default) then you would do something like the following instead:
RewriteRule (.*[^/])$ $1.php [L]
*2 Unfortunately, if you attempt to rewrite a URL that does end with a slash, this will currently fail with a 500 error since it will cause an internal rewrite loop due to the (arguably incorrect) use of REQUEST_FILENAME
in the preceding condition. A 404 would be more desirable. This can be resolved by doing the following (note the last condition) instead:
# 2. Internal rewrite to append the ".php" extension
RewriteCond %{REQUEST_URI} !^/(PhP|forms)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
See my answer to the following ServerFault question for a detailed explanation of this:
.htaccess
file?