简体   繁体   中英

Getting unique hit count in php

I want to add a unique hit counter to my website using PHP. This counter will save visitor's IP for each page in a database. I have a database structure like this:

Table hits with two columns:

ip
page_url

My question is: after getting the visitor's IP in a PHP file, which is better (for performance)?

  1. To check if the IP address is already in the database. And when not already in the database add it
  2. Just add all visitors IPs (without duplicate check) and then get distinct IPs for relevant page to get the unique hit count?

If you are on MySQL you might want to abuse the combination of PRIMARY KEY and ON DUPLICATE KEY UPDATE:

CREATE TABLE hits (
ip VARCHAR(15),
page_url VARCHAR(200),
PRIMARY KEY (ip,page_url),
hitcount INT NOT NULL DEFAULT 0
)

Now on a page hit you do

INSERT INTO hits(ip, page_url,hitcount) VALUES('$ip','$url',1)
ON DUPLICATE KEY UPDATE hitcount=hitcount+1

Why this?

  • Another unique key is POISON for a write-heavy table, so avoid it. Really.
  • INSERT ... ON DUPLICATE KEY UPDATE only locks the row once

You may also want to record the timestamp of last access:

ALTER TABLE hits ADD COLUMN lastseen TIMESTAMP();

with the help of Eugen Rieck I made my code with time and date store.

In this code, it store user ip, count,date and time.

 $ipaddress = ''; if (getenv('HTTP_CLIENT_IP')) $ipaddress = getenv('HTTP_CLIENT_IP'); else if(getenv('HTTP_X_FORWARDED_FOR')) $ipaddress = getenv('HTTP_X_FORWARDED_FOR'); else if(getenv('HTTP_X_FORWARDED')) $ipaddress = getenv('HTTP_X_FORWARDED'); else if(getenv('HTTP_FORWARDED_FOR')) $ipaddress = getenv('HTTP_FORWARDED_FOR'); else if(getenv('HTTP_FORWARDED')) $ipaddress = getenv('HTTP_FORWARDED'); else if(getenv('REMOTE_ADDR')) $ipaddress = getenv('REMOTE_ADDR'); else $ipaddress = 'UNKNOWN'; // final ip address $time=date("Y/m/d H:i:s"); // date and time in a single variable $sql = "INSERT IGNORE INTO `ipaddress` (`id`, `ipaddress`, `count`, `time`) VALUES ('', '$ipaddress','1', '$time') ON DUPLICATE KEY UPDATE count=count+1, time='".$time."'"; // adding ip,count, date and time to table if($conn->query($sql) === false) { trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR); } else { $last_inserted_id = $conn->insert_id; $affected_rows = $conn->affected_rows; } $conn->close(); 

Presuming you're comfortable with simple programming.

NOT TRULY "REAL TIME" BUT ALMOST REAL TIME Highly recommend you to write out to a log with your own format to a text file (if you're not comfortable with Apache's [customlog][1] feature).

Then, set up a cronjob every 5 minutes, or even once every 1 minute if you want close to "live", import the text into a MySql temporary table in a big gulp with LOAD DATA INFILE and then update your visitcounts table based on GROUP BY ip.

FULLY REAL TIME This can be a huge drag on your server but given that you have light traffic just create two tables in MySQL. One just records the article/page ID being read + IP + time (log table). The other contains article/page ID and visit counts--where the counts are updated GROUP BY ip in the first table.

I would use unique key on ( ip , page_url ), optionally date . If the record isn't there it would be create, it would cause error otherwise (but you can easily check error code) or you could use IGNORE in INSERT statement..

It'd take only one request to the database and would be probably the fastest. You would have also automatically guaranteed that all records will be unique and you wouldn't need to use a transaction.

Hi john and fellow flow peeps... I'm new to programming and MYSQL, ...however the way I got round it was the following:

I use some PHP code to query the hits DB and then evaluate both columns, ip and page_url and if they evaluate to true do nothing, else ...insert/execute the code shown above by Eugene Rick...

$ip = $_SERVER['REMOTE_ADDR']; // Get IP Address.

$purl = htmlspecialchars($_GET['page_url']); // Get Page URL.

$results = $mysqli->query("select * from hits"); // Query hits table.

$row = $results->fetch_assoc(); // Fetch array and assign to $row, then evaluate with if statement.

if ($row['ip'] == $ip && $row['page_url'] == $purl) {

} else {
    $mysqli->query("insert into hits (ip,page_url,counter) values ('$ip','$purl',1) on duplicate key update counter=counter+1");
}

I'll be honest I have not checked this on more than one IP address, just mine.

However it adds rows to the hits table for each URL inserted based on an unique ip (the one I'm currently using) and does not increment the hits count for any inserted URL when the page is refreshed so I assume it works...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM