I recently started working with the rewrite engine and asked for help on removing the PHP extension and adding a trailing slash to URLs. A perfectly working solution was provided by anubhava here. For a quick reference, the configuration file is provided below:
.htaccess
RewriteEngine On
# removes .php and adds a trailing /
# i.e. to externally redirect /path/file.php to /path/file/
RewriteCond %{THE_REQUEST} s/+(.+?).php[s?] [NC]
RewriteRule ^ /%1/ [R=307,NE,L]
# adds a trailing slash to non files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=307,NE]
# internally rewrites /path/file/ to /path/file.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)/$ $1.php [L]
This configuration works as intended for URLs like:
https://example.com/test.php
https://example.com/test
https://example.com/test/
The URLs above are all rewritten to:
https://example.com/test/
So far so good, except that if the PHP file contains a query string, it works a little differently than I would like. For example, if the URL is:
https://example.com/test.php?lang=en&id=3
Then it is rewritten to:
https://example.com/test/?lang=en&id=3
Unfortunately, I did not anticipate this problem, which is causing me issues because I cannot capture the query string in the PHP file below.
test.php
<?php
session_start();
if(isset($_GET['lang']))
{
$_SESSION['lang'] = $_GET['lang'];
}
?>
To resolve this, I need a method to capture the PHP query string. I think rewriting the URL to https://example.com/test?lang=en&id=3/
could work. However, I’m open to alternative solutions.
Edit: Given the complexity of the problem, the trailing slash is optional, but I would like to remove the PHP extension and be able to capture the query string.
2
Answers
Considering our discussion in the comments, this (though only very roughly tested on a flawed online htaccess tester) should work.
Noticed I removed the adding of the ‘/’ exceptif there is a real directory. Adding a / has a significant meaning for an URL (it refers to a directory, not to a file!) so just adding it for beauty makes no sense, it is exactly why everything became complicated and went wrong.
If you use routing (for instance in Laravel or another platform) of course you can do with the url whatever you want, but since you don’t seem to be, and seem to need the URL match to a file on your server, you just really don’t want to add random slashes.
NOTE: this example now choses the directory if both a directory and a file exists, i.e. with
path/name/*
andpath/name.php
both existing, the dir is chosen. If you don’t want that, I think switching the last two blocks around will do the trick.The RewriteRule directive allows for a QSA flag that copies the query string to the rewritten URL.
So your
[L]
flags should be something like[L,QSA]
.For additional doc, you can find the list of available flags for the RewriteRule directive.
I found this out by reading the Fat-Free Framework
.htaccess
sample.