我想使用PHP为我的网站添加一个独特的点击计数器。此计数器将为数据库中的每个页面保存访问者的IP。我有这样的数据库结构:
表hits
有两列:
ip
page_url
我的问题是:在PHP文件中获取访问者的IP后,哪个更好(性能)?
答案 0 :(得分:6)
如果你使用MySQL,你可能想滥用PRIMARY KEY和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
)
现在点击页面即可
INSERT INTO hits(ip, page_url,hitcount) VALUES('$ip','$url',1)
ON DUPLICATE KEY UPDATE hitcount=hitcount+1
为什么会这样?
您可能还想记录上次访问的时间戳:
ALTER TABLE hits ADD COLUMN lastseen TIMESTAMP();
答案 1 :(得分:2)
假设您对简单编程感到满意。
不是真正的“实时”,但几乎是实时
强烈建议您使用自己的格式写入日志文本文件(如果您对Apache的[customlog][1]
功能不满意)。
然后,每5分钟设置一个cronjob,如果你想要接近“live”,甚至每1分钟设置一次cronjob,将文本导入到LOAD DATA INFILE
的大口中的MySql临时表中,然后更新你的基于GROUP BY ip的visitcounts表。
完全实时 这可能会严重拖累您的服务器,但鉴于您拥有轻量级流量,只需在MySQL中创建两个表。一个只记录正在读取的文章/页面ID + IP +时间(日志表)。另一个包含文章/页面ID和访问计数 - 其中计数更新在第一个表中的GROUP BY ip。
答案 2 :(得分:2)
在Eugen Rieck的帮助下,我用时间和日期存储创建了代码。
在此代码中,它存储用户ip,计数,日期和时间。
$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();

答案 3 :(得分:1)
我会在(ip
,page_url
)上使用唯一键,可选date
。如果记录不存在则会创建,否则会导致错误(但您可以轻松检查错误代码),或者您可以在IGNORE
语句中使用INSERT
。
它只需要一个数据库请求,可能是最快的。您还可以自动保证所有记录都是唯一的,您不需要使用交易。
答案 4 :(得分:0)
嗨,约翰和其他流程偷看......我是编程和MYSQL的新手,...但是我绕过它的方式如下:
我使用一些PHP代码来查询命中数据库,然后评估两列ip
和page_url
,如果它们评估为true则不执行任何操作,否则 ...插入/执行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");
}
我会说实话,我没有在多个IP地址上检查过这个,只是我的。
然而,它为每个基于唯一ip(我正在使用的那个)插入的URL添加了hits表的行,并且当刷新页面时不会增加任何插入的URL的命中数,所以我认为它有效...