I'm trying to use .htaccess
to make pretty URLs for my site. Here's the code:
RewriteEngine On
RewriteBase /
ErrorDocument 404 /404.php
RewriteCond %{THE_REQUEST} ^GET\ /post\.php\?id=([^\s&]+)&name=([^\s&]+) [NC]
RewriteRule ^ /post/%1/%2$ [R=301,L,NE]
RewriteRule ^post/([^/]+)/([^/]+)/?$ post.php?id=$1&name=$2 [NC,L]
And inside my post.php
page, I have a simple view counter:
$url = substr($_SERVER['REQUEST_URI'],1);
$url = explode('/',$url);
$id_post = $purifier->purify($url[1]);
$post = $db->selectone("select p.*, u.username from tx_post p inner join user u on p.id_user = u.id_user where id_post = :id_post",[':id_post'=>$id_post]);
echo 'VIEWS:'.$post['views'].'<br>';
$views = $post['views']+1;
echo 'views after:'.$views.'<br>';
$db->update('tx_post',['views'=>$views],'id_post='.$id_post);
Now here is my problem: when I go to the URL example.com/post/78
(without the final slash) everything works fine. The counter gets what's in the database and increment by 1 just like it should. However, if I put the final slash (example.com/post/78/
), the counter increments 26. Obviously the same thing happens when I pass another parameter (like how I intend to do - example.com/post/78/postname/
).
The counter doesn't have any other increment on the page, so I'm assuming it's executing the page multiple times (if that's even possible, I don't know much about web servers).
Any ideas what may be causing this?
There doesn't seem to be any good reason in the code you posted why the counter should be going crazy like that? However, the .htaccess
directives you've posted would not be getting processed at all for a request like example.com/post/78
(no slash) or example.com/post/78/
(with slash) - the regex simply does not match. This suggests MultiViews
is enabled.
Also, it seems odd that you extracting the id
from the REQUEST_URI
server variable when you are supposedly passing this in the URL parameter? This also suggests MultiViews
is taking over. You'll need MultiViews
disabled for these directives to function as intended. At the top of your .htaccess
file you should add the following:
# Disable MultiViews
Options -MultiViews
Since /post/78
maps directly to a file of the same name but with a .php
extension then with MultiViews
enabled mod_negotiation ends up issuing an internal subrequest for /post.php
- without any URL parameters.
Note that the directives you posted only appear to match URLs of the form /post/<id>/<postname>
(with or without the trailing slash). To match /post/<id>
only, you'll need an additional directive, or modify your existing directive to match both.
For example:
RewriteRule ^post/([^/]+)(?:/([^/]+))?/?$ post.php?id=$1&name=$2 [NC,L]