apache – php counter going crazy with .htaccess-ThrowExceptions

Exception or error:

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?

How to solve:

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]

Leave a Reply

Your email address will not be published. Required fields are marked *