2

I am currently using the following in /public_html/.htaccess to strip .php extensions and force trailing slashes.

# Remove .php extension
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/(.+)/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^(.*)/$ $1.php [L]

# Force trailing slash
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]

This works perfectly, however, there are a number of PHP files in subfolders of /public_html that we don't want to be rewritten.

How can I modify the rewrite + trailing slash to apply only to PHP files in the /public_html folder, or, to specify a list of PHP files that the rule applies to?

UPDATE: In my case, I believe the optimal solution will be to strip the PHP extension (and add trailing slash) only to files explicitly specified, rather than creating folder-based conditions.

UPDATE 2: Working solution:

#Remove PHP extension from named files
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(file1|file2)/?$ /$1.php [L,NC]
2
  • Is your "update 2" in its entirety?
    – MrWhite
    Sep 26, 2016 at 17:21
  • Yes, that's the entire relevant portion. The actual .htaccess is much longer, but everything else (aside from the obvious RewriteEngine On directive) is unrelated to this issue.
    – Nathan
    Nov 18, 2017 at 19:37

1 Answer 1

1

You could simply make an exception at the start of your .htaccess file... if the request matches one of these subfolders (and is an existing PHP file?) then stop the rewriting process. For example:

RewriteRule ^(subfolder1|subfolder2)$ - [L]

If you simply want to skip all requests then you can stop there. If you specifically need to only skip the rewrites if it matches existing PHP files then:

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(subfolder1|subfolder2)/.+\.php$ - [L]

If the request if for /subfolder1/<something>.php and that file exists then stop here.

UPDATE#1:

We only want this to apply to PHP files in /public_html, and none of its subfolders

You could probably still do this with an exception before your existing rules. If the request contains a slash (ie. it's for a subfolder) then abort. For example:

RewriteRule /.*/?$ - [L]

Alternatively, change the pattern in your existing RewriteRules to match anything except a slash (ie. [^/]*) instead of literally everything (ie. .*). Applied to your existing rules:

RewriteRule ^([^/]*)\.php$ /$1/ [L,R=301]
:
RewriteRule ^([^/]*)/$ $1.php [L]
:
RewriteRule ^[^/]*$ $0/ [L,R=301]

UPDATE#2: Added anchors to the above RewriteRule patterns.

UPDATE#3: To make the above apply to only specific files in the document root. You would use an exception (as in the above) that excludes all other files. For example:

RewriteRule !^(file1|file2|file3|file4) - [L]

In order to allow all URLs that start /file1, /file2, /file3, etc. (The URL matched by the RewriteRule pattern does not start with a slash in per-directory .htaccess files.)

In context...

Options -MultiViews
RewriteEngine On

# Only allow specific requests to be processed...
RewriteRule !^(file1|file2|file3|file4) - [L]

# Remove .php extension
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]

# Force trailing slash
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]

# Route request...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/(.+)/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^(.*)/$ $1.php [L]
16
  • Thank you. How could I change this so I'm specifying the folders the rule should apply to, rather than the folders it does NOT apply to? We only want this to apply to PHP files in /public_html, and none of its subfolders (of which there are too many to list explicitly if we can avoid it). Also, what would the full htaccess be in that case? I'm a bit unclear where to place this, as currently the line RewriteCond %{REQUEST_FILENAME}.php -f is second to last, as part of the force trailing slash code.
    – Nathan
    Sep 26, 2016 at 13:01
  • Place any exception "at the start of your .htaccess file". You could still use an exception to apply only to requests in the root. Or you change your existing RewriteRule pattern. I've updated my answer.
    – MrWhite
    Sep 26, 2016 at 14:31
  • Corrected regex in the first pattern after update
    – MrWhite
    Sep 26, 2016 at 14:50
  • Thanks for the update. Unfortunately, neither solution had the desired effect. Here is what I tried: pastebin.com/eK3YkrCH I think the simplest solution in our case would be to explicitly list the PHP files in public_html that this rewrite should apply to (there are only 5). Is this possible?
    – Nathan
    Sep 26, 2016 at 15:08
  • What actually happens? Have you cleared your browser cache (or test with caching disabled)? Any earlier/erroneous 301s will have been cached by the browser.
    – MrWhite
    Sep 26, 2016 at 15:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .