計數器是早期 PHP 入門必寫的小專案。本文提供兩種經典實作:純文字儲存與圖形化數字圖片顯示。雖然現代網站多改用 Google Analytics、Matomo 或資料庫統計,但理解檔案鎖定、原子寫入、圖片拼接等基礎技術,對學習 PHP 檔案操作與併發控制極有幫助。
counter_text.php<?php
$countfile = "/count.txt"; // 建議放在網站根目錄外的可寫目錄
// 1. 檔案不存在則建立並初始化為 0
if (!file_exists($countfile)) {
file_put_contents($countfile, '0', LOCK_EX);
}
// 2. 讀取、遞增、寫回(使用檔案鎖定防止競態條件)
$fp = fopen($countfile, "c+"); // 開啟讀寫,指標在開頭,不截斷
if (flock($fp, LOCK_EX)) { // 獨佔鎖定
$num = (int)fgets($fp, filesize($countfile));
$num++;
ftruncate($fp, 0); // 清空檔案
rewind($fp);
fwrite($fp, (string)$num);
flock($fp, LOCK_UN); // 釋放鎖定
}
fclose($fp);
echo "訪問量總計: {$num} 人次";
?>
exec("rm ...") + exec("echo ...") 極度不安全且效能差,改用 fopen/flock/ftruncate/fwrite 原子操作。"c+" 模式:檔案不存在會建立,存在則不截斷,指標在開頭。public_html 外層,避免被直接下載。counter_image.php原理:將數字拆解為個位、十位...,每位對應一張 0.gif~9.gif 圖片,輸出 <img> 標籤串聯。
<?php
$countfile = "/count-num.txt";
if (!file_exists($countfile)) {
file_put_contents($countfile, '0', LOCK_EX);
}
$fp = fopen($countfile, "c+");
if (flock($fp, LOCK_EX)) {
$num = (int)fgets($fp, filesize($countfile));
$num++;
ftruncate($fp, 0);
rewind($fp);
fwrite($fp, (string)$num);
flock($fp, LOCK_UN);
}
fclose($fp);
// 產生圖片標籤串
$num_str = (string)$num;
$out_str = '';
for ($i = 0; $i < strlen($num_str); $i++) {
$digit = $num_str[$i];
$out_str .= '<img src="' . htmlspecialchars($digit) . '.gif" alt="' . $digit . '">';
}
echo "訪問量總計: {$out_str} 人次";
?>
| 問題 | 檔案計數器現狀 | 解決方案 |
|---|---|---|
| 併發效能 | 檔案鎖定序列化,QPS 低 | 改用 Redis INCR、MySQL UPDATE ... SET count=count+1、Memcached increment |
| 多伺服器同步 | 單機檔案無法共享 | 集中式儲存或分散式計數器 |
| 機器人流量污染 | 所有請求皆計數 | 前端 JS 觸發 / 後端 UA 過濾 / Cloudflare Turnstile |
| 資料持久化 | 檔案易遺失、備份麻煩 | 資料庫備份策略、RDB/AOF 持久化 |
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = 'site:pv:total';
$pv = $redis->incr($key); // 原子遞增,極高效能
echo "訪問量總計: {$pv} 人次";
?>
https://img.shields.io/badge/Views-12345-blue 即時生成。檔案計數器是理解「讀取-修改-寫入」併發模型的最佳教具。實務上,請直接使用成熟的分析工具或分散式計數服務;若需自建,Redis/Memcached 是極佳的平衡點。