| 維度 | PHP 後端統計 | JavaScript 前端統計 |
|---|---|---|
| 資料來源 | HTTP 請求自動攜帶 Cookie | document.cookie 讀寫 |
| 準確度 | 含機器人/爬蟲 | 需 JS 執行環境,可過濾部分鏈爬蟲 |
| 持久化 | 伺服器端 Session/DB | 瀏覽器 Cookie(受同源策略限制) |
| 適用場景 | 精確統計、後端邏輯綁定 | 輕量展示、無後端依賴頁面 |
<?php
// 設定 Cookie 參數
$cookieName = 'visit_stats';
$expireDays = 365;
$expireTime = time() + $expireDays * 86400;
$domain = ''; // 當前域名
$path = '/';
$secure = isset($_SERVER['HTTPS']); // HTTPS 才傳送
$httponly = true; // 防 XSS
// 讀取現有統計
$stats = isset($_COOKIE[$cookieName]) ? json_decode($_COOKIE[$cookieName], true) : [
'count' => 0,
'firstVisit' => 0,
'lastVisit' => 0,
];
$stats['count']++;
$now = time();
if ($stats['firstVisit'] === 0) $stats['firstVisit'] = $now;
$stats['lastVisit'] = $now;
// 寫回 Cookie
setcookie($cookieName, json_encode($stats), $expireTime, $path, $domain, $secure, $httponly);
// 輸出顯示
$visitMsg = $stats['count'] === 1
? '歡迎首次造訪本站!'
: sprintf('您是第 %d 次造訪,上次時間:%s', $stats['count'], date('Y-m-d H:i:s', $stats['lastVisit']));
echo "<p>$visitMsg</p>";
?>
<script>
(function () {
const COOKIE_NAME = 'visit_stats';
const EXPIRE_DAYS = 365;
// 解析 Cookie 字串
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^|;\\s*)' + name + '=([^;]+)'));
return match ? JSON.parse(decodeURIComponent(match[2])) : null;
}
// 寫入 Cookie
function setCookie(name, value, days) {
const exp = new Date();
exp.setTime(exp.getTime() + days * 864e5);
document.cookie = `${name}=${encodeURIComponent(JSON.stringify(value))};expires=${exp.toUTCString()};path=/;SameSite=Lax`;
}
let stats = getCookie(COOKIE_NAME) || { count: 0, firstVisit: 0, lastVisit: 0 };
stats.count++;
const now = Date.now();
if (!stats.firstVisit) stats.firstVisit = now;
stats.lastVisit = now;
setCookie(COOKIE_NAME, stats, EXPIRE_DAYS);
// 顯示訊息(可自訂 UI)
const msg = stats.count === 1
? 'Welcome! First visit.'
: `Visit #${stats.count}. Last: ${new Date(stats.lastVisit).toLocaleString()}`;
console.log(msg);
// document.getElementById('visit-counter').textContent = msg;
})();
</script>
前端 JS 僅負責觸發「唯一訪客」判斷,實際計數由後端 API 完成:
<?php // api/visit.php
session_start();
header('Content-Type: application/json');
$visitorId = $_COOKIE['visitor_id'] ?? bin2hex(random_bytes(16));
setcookie('visitor_id', $visitorId, time() + 365*86400, '/', '', true, true);
// Redis 範例:HyperLogLog 估算唯一訪客
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->pfadd('site:visitors', $visitorId);
$total = $redis->pfcount('site:visitors');
echo json_encode(['visitor_id' => $visitorId, 'unique_visitors' => $total]);
?>
// 前端呼叫
fetch('/api/visit.php', {credentials: 'include'})
.then(r => r.json())
.then(d => console.log('Unique visitors:', d.unique_visitors));
SameSite=None; Secure。PHP 方案適合需精確記錄、綁定會員系統的場景;JS 方案部署簡單、不受後端快取影響。生產環境建議採用「前端觸發 + 後端 Redis/DB 聚合」架構,兼顧效能與準確度。