您现在的位置是:时尚 >>正文
PHP实现简单网站访客统计的方法实例
时尚6555人已围观
简介用PHP做访客统计,最直接的办法就是每次有人打开页面时,往数据库里插一条记录。别急着想什么高性能方案,小网站一天几百几千的访问量,这套逻辑跑起来绰绰有余。我见过不少人一上来就上Redis、上消息队列, ...
用PHP做访客统计,实实例最直接的现简办法就是每次有人打开页面时,往数据库里插一条记录。单网别急着想什么高性能方案,站访小网站一天几百几千的客统访问量,这套逻辑跑起来绰绰有余。实实例我见过不少人一上来就上Redis、现简上消息队列,单网结果服务器上连MySQL都还没装明白。站访
先建一张表。客统字段不用多,实实例够用就行。现简我习惯用下面这个结构:
CREATE TABLE visitor_log ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,单网 ip VARCHAR(45) NOT NULL, visit_time DATETIME NOT NULL, user_agent VARCHAR(255) DEFAULT NULL, page_url VARCHAR(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ip字段给45个字符,是站访因为IPv6最长就这么长。别用15个字符的客统老写法,迟早要吃亏。visit_time用DATETIME,别用TIMESTAMP,省得2038年还要改代码。page_url可以记下访客看的是哪个页面,后面分析起来方便。
接下来写PHP。核心就一段:连数据库、拼SQL、执行。我把它写成一个函数放在公共文件里,每个页面顶部include一下就行。
function logVisit($pdo) { $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $ua = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 255); $url = substr($_SERVER['REQUEST_URI'] ?? '', 0, 255); $stmt = $pdo->prepare( "INSERT INTO visitor_log (ip, visit_time, user_agent, page_url) VALUES (?, NOW(), ?, ?)" ); $stmt->execute([$ip, $ua, $url]); } 用PDO预处理,别直接拼字符串。我见过有人写"INSERT ... VALUES ('$ip', ...)",结果被注入搞到删库。这种亏吃一次就够了。
调用的时候在页面开头写:
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass'); logVisit($pdo); 到这里基本功能就完成了。但有个问题:同一个人刷新五次页面,就记五条。这算不算重复?看你需求。如果只想统计“有多少人来过”,得去重。
去重的简单做法是按IP加时间窗口判断。比如同一个IP一小时内只记一次:
function logVisitUnique($pdo) { $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $stmt = $pdo->prepare( "SELECT COUNT(*) FROM visitor_log WHERE ip = ? AND visit_time > DATE_SUB(NOW(), INTERVAL 1 HOUR)" ); $stmt->execute([$ip]); if ($stmt->fetchColumn() == 0) { logVisit($pdo); } } 这个逻辑对家用宽带够用。但移动网络下,同一个基站出来的IP可能一样,会漏记。要更准就得靠Cookie或Session,不过那又是另一回事了。
统计展示部分,写个简单查询:
$today = $pdo->query( "SELECT COUNT(DISTINCT ip) FROM visitor_log WHERE DATE(visit_time) = CURDATE()" )->fetchColumn(); echo "今日访客:{ $today} 人"; 用COUNT(DISTINCT ip)去重,比COUNT(*)更接近“人数”的概念。当然,前面说了,IP去重不完美,但小站够用。
有个细节要注意:logVisit函数每次请求都写一次数据库,页面加载会慢几毫秒。如果页面本身查询就多,建议把统计逻辑放到页面输出之后,用fastcgi_finish_request()先返回内容再写日志。Nginx + PHP-FPM环境下这招很实用。
// 页面内容输出完之后 if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } logVisit($pdo); 这样用户感觉不到统计带来的延迟。我第一次用这函数的时候,感觉像发现了新大陆。
数据量大了怎么办?比如超过十万条,查询变慢。加个索引就行:
ALTER TABLE visitor_log ADD INDEX idx_time (visit_time); ALTER TABLE visitor_log ADD INDEX idx_ip_time (ip, visit_time); 再大就按月分表,或者定期删旧数据。我一般保留三个月,写个定时任务每天凌晨清理一次。别让日志表无限膨胀,硬盘满了比代码bug更麻烦。
最后说个实际踩过的坑。有次帮朋友看他的统计代码,发现数据涨得特别快,一天好几万。查了半天,原来是他自己写了个爬虫在测试,没带User-Agent,全被记进去了。后来加了个简单过滤:
if (empty($_SERVER['HTTP_USER_AGENT'])) { return; // 不记录空UA的请求 } 这招挡不住所有爬虫,但能过滤掉一大部分。真要防,还得靠robots.txt和更复杂的识别逻辑,那就超出“简单统计”的范围了。
整套代码加起来不到五十行,丢到一个文件里就能跑。别把它想复杂了,先跑起来,有问题再改。
Tags:
上一篇:直播间黑粉屏蔽词100个
下一篇:系统魔方
相关文章
水压渗透深度试验装置
时尚实验室角落那台不锈钢装置,个头不大,压力表盘却亮得扎眼。水压渗透深度试验,说白了就是模拟水往混凝土缝里钻的狠劲儿。别小看这个“钻”字——大坝、隧道、地下室,渗水是头号杀手。这装置就是给材料上刑的,逼着 ...
【时尚】
阅读更多线上推广引流渠道
时尚线上推广引流渠道,说白了就是一场争夺注意力的巷战。你手里攥着预算和产品,但用户的手指头永远比你的广告语滑得更快。别指望一条渠道吃遍天,那跟拿着勺子挖矿没区别。 拿我最近盯的一个母婴品牌来说。他们砸了两 ...
【时尚】
阅读更多网络安全简报范文
时尚网络安全简报范文 周三凌晨两点十七分,某电商平台的防火墙日志突然涌入四千条异常请求。攻击者没有用暴力破解,而是精准调用了三年前泄露的员工邮箱密码,直接登录了后台管理账号。整个入侵过程只用了一分零八秒— ...
【时尚】
阅读更多