5

I need to create a counter for member section (count the number of times a user logged).

I have the following script (counter.php):

<?php
    $conn = mysql_connect("localhost", "myuser", "mypass");
    mysql_select_db("test");

    $sql = "SELECT views FROM members WHERE mid = " . $_GET['mid'];     
    $result = mysql_query($sql); 
    if (!$result)
        {
        mail(ADMIN, 'Cannot Get: ' . mysql_error(), mysql_error());  
        }
    while ($row = mysql_fetch_assoc($result)) 
        {
        $count = $row['views']++; 
        }
    $query = "UPDATE members SET views = '$count' WHERE mid = " . $_GET['mid']; 
    mysql_query($query); 
    mysql_close($conn);

    // show the logo using header() and readfile(); // that part work
?>

DB:

CREATE TABLE `members` (
  `mid` int(11) NOT NULL AUTO_INCREMENT,
  `views` int(11) DEFAULT '0',
  /* etc...*/
  PRIMARY KEY (`mid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Now, what I do in my .htaccess file is:

RewriteEngine On
RewriteRule ^img/logo([0-9]+).jpg$ /counter.php?mid=$1 [L]

but for some reason my counter does not count correctly. What am I missing?

4
  • 1
    Be sure to learn all about SQL injection and input filtering. Commented Oct 17, 2011 at 18:29
  • Indeed. Don't try to put the id mid=1;delete%20from%20members;-- in the url. :) Commented Oct 17, 2011 at 18:32
  • I thought the ([0-9]+) will prevent that, it does not? Commented Oct 17, 2011 at 18:43
  • the rewrite rule is not providing any security at all, its just a url alias. Someone could just as easily hit up counter.php with the sql injection parameters Commented Oct 17, 2011 at 19:27

3 Answers 3

12

You could probably just simplify it and do the following:

$query = "UPDATE members SET views = views + 1 WHERE mid = " . $_GET['mid']; 
mysql_query($query); 

if (mysql_affected_rows() == 0) {
   mail(ADMIN, 'Cannot Get: ' . mysql_error(), mysql_error());
}

mysql_close($conn);

No need to do initial check.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 Not only is this more efficient than doing two queries, but database locking will help prevent multiple concurrent requests from being counted as 1.
Smart thinking. Less risk on issues with simultaneous counts indeed.
This is going to be hardly inefficient if you get a lot of visitors, since the database locks will block the system too heavy. Try to read more about sharded counters, used @ google's appengine
5

use this

$count = $row['views'] + 1;

or

$count = ++$row['views'];

or

$query = "UPDATE members SET views = views + 1 WHERE mid = " . $_GET['mid'];

syntax:

$x = 1;
$count = $x++;
// $count = 1

$x = 1;
$count = ++$x;
// $count = 2

3 Comments

+1 I don't see what's wrong with this. Downvoter, care to enlighten us?
Failed to address the actual cause of the problem at first. But it seems ok after he copied my answer. ;-) Although it still could do Undone my downvote, because at least the answer now addresses the problem, although it could do with a little more explanation.
@GolezTrol: I see. Your answer does have a better explanation of pre- and post-increment. I've upvoted you.
2

The problem is in the line

$count = $row['views']++; 

This actually says:
- Assign the value of view to $count
- Increment views.

But you want:

$count = ++$row['views']; 

Which says:
- Increment views.
- Assign the (incremented) value of view to $count

A subtle difference. :~)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.