PHP Cookies 完全指南

Cookie是存储在用户浏览器中的小型文本文件,用于在多个页面请求之间持久化数据。Cookie是构建现代Web应用程序的关键技术之一,广泛应用于用户认证、偏好设置、会话管理等功能。

Cookie工作原理:当服务器需要存储一些用户数据时,它会发送一个Set-Cookie头给浏览器。浏览器将该数据存储在本地,并在后续请求中自动发送回服务器。

什么是Cookie?

Cookie是服务器发送到用户浏览器并保存在本地的小型数据片段,每次浏览器向同一服务器发送请求时,都会携带这些数据。Cookie的主要用途包括:

  • 用户识别:识别重复访问的用户
  • 会话管理:维护用户的登录状态
  • 个性化设置:存储用户偏好(如主题、语言)
  • 跟踪分析:分析用户行为和网站使用情况
  • 购物车功能:在电商网站中存储购物车信息
重要提示:Cookie存储在用户本地,存在一定的安全风险。不应在Cookie中存储敏感信息(如密码、信用卡号等)。同时要注意遵守GDPR等隐私法规。

Cookie的基本结构

每个Cookie包含以下主要属性:

// Cookie的基本参数
setcookie(
    name,        // Cookie名称
    value,       // Cookie值
    expire,      // 过期时间(时间戳)
    path,        // 服务器上的有效路径
    domain,      // Cookie有效的域名
    secure,      // 是否仅通过HTTPS传输
    httponly     // 是否仅可通过HTTP访问(防止JavaScript访问)
);

创建和设置Cookie

1. 基本Cookie设置

<?php
// 注意:setcookie()函数必须在任何HTML输出之前调用
// 否则会产生"headers already sent"错误

// 设置一个简单的Cookie,30分钟后过期
setcookie("user_name", "张三", time() + 1800);

// 设置带多个参数的Cookie
setcookie(
    "user_preferences",
    json_encode(['theme' => 'dark', 'language' => 'zh-CN']),
    time() + (30 * 24 * 60 * 60),  // 30天过期
    "/",                            // 整个网站有效
    "example.com",                  // 指定域名
    true,                           // 仅通过HTTPS传输
    true                            // 仅HTTP访问(防止JavaScript访问)
);

echo "Cookie已设置成功!";
?>

<!DOCTYPE html>
<html>
<head>
    <title>设置Cookie示例</title>
</head>
<body>
    <p>页面内容...</p>
</body>
</html>

2. 使用setrawcookie()

setrawcookie()setcookie()功能相同,但不会对Cookie值进行URL编码。

<?php
// setcookie()会自动进行URL编码
setcookie("test1", "value with spaces", time() + 3600);
// 存储的值会是 "value%20with%20spaces"

// setrawcookie()不进行URL编码
setrawcookie("test2", "value with spaces", time() + 3600);
// 存储的值保持为 "value with spaces"

echo "使用setrawcookie()设置的Cookie不会进行URL编码。";
?>

3. 设置Cookie数组

<?php
// 方法1:使用名称数组
setcookie("user[name]", "张三", time() + 3600);
setcookie("user[email]", "zhangsan@example.com", time() + 3600);
setcookie("user[preferences]", json_encode(['theme' => 'dark']), time() + 3600);

// 方法2:使用JSON编码
$userData = [
    'name' => '张三',
    'email' => 'zhangsan@example.com',
    'preferences' => ['theme' => 'dark', 'language' => 'zh-CN']
];

setcookie("user_data", json_encode($userData), time() + 3600);

echo "Cookie数组设置完成!";
?>

读取Cookie值

1. 基本读取操作

<?php
// 读取单个Cookie
if (isset($_COOKIE['user_name'])) {
    $userName = htmlspecialchars($_COOKIE['user_name']);
    echo "欢迎回来," . $userName . "!<br>";
} else {
    echo "这是您第一次访问本网站。<br>";
}

// 读取Cookie数组
if (isset($_COOKIE['user'])) {
    $user = $_COOKIE['user'];
    echo "用户名: " . htmlspecialchars($user['name'] ?? '') . "<br>";
    echo "邮箱: " . htmlspecialchars($user['email'] ?? '') . "<br>";

    // 解码JSON数据
    if (isset($user['preferences'])) {
        $preferences = json_decode($user['preferences'], true);
        if ($preferences) {
            echo "主题设置: " . ($preferences['theme'] ?? '默认') . "<br>";
        }
    }
}

// 读取JSON编码的Cookie
if (isset($_COOKIE['user_data'])) {
    $userData = json_decode($_COOKIE['user_data'], true);
    if ($userData) {
        echo "用户数据: <pre>" . print_r($userData, true) . "</pre>";
    }
}
?>

2. 安全读取Cookie

<?php
/**
 * 安全读取Cookie值的函数
 * @param string $name Cookie名称
 * @param mixed $default 默认值
 * @return mixed 安全的Cookie值
 */
function getSecureCookie($name, $default = null) {
    if (!isset($_COOKIE[$name])) {
        return $default;
    }

    $value = $_COOKIE[$name];

    // 对字符串进行安全过滤
    if (is_string($value)) {
        $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    }

    // 如果是JSON字符串,尝试解码并递归过滤
    if (is_string($value) && ($decoded = json_decode($value, true)) !== null) {
        $value = array_map(function($item) {
            return is_string($item) ? htmlspecialchars($item, ENT_QUOTES, 'UTF-8') : $item;
        }, $decoded);
    }

    return $value;
}

// 使用安全函数读取Cookie
$safeUserName = getSecureCookie('user_name', '访客');
echo "安全用户名: " . $safeUserName;

// 读取并验证重要数据
$sessionToken = getSecureCookie('session_token');
if ($sessionToken && validateSessionToken($sessionToken)) {
    // 有效的会话令牌
    echo "会话验证成功!";
}

function validateSessionToken($token) {
    // 在实际应用中,这里应该验证令牌的有效性
    return strlen($token) === 64 && ctype_xdigit($token);
}
?>

3. 查看所有Cookie

<?php
// 显示所有Cookie(调试用途)
function displayAllCookies() {
    echo "<h3>当前所有Cookie:</h3>";

    if (empty($_COOKIE)) {
        echo "<p>没有找到Cookie。</p>";
        return;
    }

    echo "<table border='1' cellpadding='8' cellspacing='0' style='border-collapse: collapse;'>";
    echo "<thead><tr><th>Cookie名称</th><th>值</th><th>大小</th></tr></thead>";
    echo "<tbody>";

    foreach ($_COOKIE as $name => $value) {
        $safeName = htmlspecialchars($name);
        $safeValue = htmlspecialchars(substr($value, 0, 100)) . (strlen($value) > 100 ? '...' : '');
        $size = strlen($value);

        echo "<tr>";
        echo "<td><code>$safeName</code></td>";
        echo "<td style='word-break: break-all;'>$safeValue</td>";
        echo "<td>$size 字节</td>";
        echo "</tr>";
    }

    echo "</tbody></table>";

    // 统计信息
    echo "<p>总计: " . count($_COOKIE) . " 个Cookie</p>";
    echo "<p>总大小: " . array_sum(array_map('strlen', $_COOKIE)) . " 字节</p>";
}

// 仅在调试模式下显示
if (defined('DEBUG_MODE') && DEBUG_MODE) {
    displayAllCookies();
}
?>

删除Cookie

1. 基本删除方法

<?php
// 方法1:将过期时间设置为过去的时间
setcookie("user_name", "", time() - 3600);

// 方法2:清空值并设置过期时间
setcookie("session_token", "", time() - 3600, "/", "example.com", true, true);

// 方法3:删除Cookie数组的特定元素
if (isset($_COOKIE['user']) && is_array($_COOKIE['user'])) {
    setcookie("user[preferences]", "", time() - 3600);
}

echo "Cookie删除成功!<br>";

// 验证Cookie是否已删除
if (!isset($_COOKIE['user_name'])) {
    echo "user_name Cookie已被成功删除。";
}
?>

2. 批量删除Cookie

<?php
/**
 * 批量删除Cookie
 * @param array $cookiesToDelete 要删除的Cookie名称数组
 */
function deleteCookies(array $cookiesToDelete) {
    foreach ($cookiesToDelete as $cookieName) {
        // 检查Cookie是否存在
        if (isset($_COOKIE[$cookieName])) {
            // 设置为过期
            setcookie($cookieName, "", time() - 3600);

            // 从当前请求的$_COOKIE数组中移除
            unset($_COOKIE[$cookieName]);
        }
    }
}

/**
 * 删除特定前缀的所有Cookie
 * @param string $prefix Cookie名称前缀
 */
function deleteCookiesByPrefix($prefix) {
    foreach ($_COOKIE as $name => $value) {
        if (strpos($name, $prefix) === 0) {
            setcookie($name, "", time() - 3600);
            unset($_COOKIE[$name]);
        }
    }
}

// 使用示例
$cookiesToRemove = ['session_id', 'user_preferences', 'tracking_token'];
deleteCookies($cookiesToRemove);

// 删除所有以"temp_"开头的Cookie
deleteCookiesByPrefix("temp_");

echo "批量删除操作完成!";
?>

Cookie有效期管理

1. 设置不同的有效期

<?php
// 会话Cookie(浏览器关闭时过期)
setcookie("session_cookie", "value", 0);  // 0表示会话Cookie

// 短期Cookie(1小时)
setcookie("short_term", "value", time() + 3600);

// 中期Cookie(7天)
setcookie("medium_term", "value", time() + (7 * 24 * 60 * 60));

// 长期Cookie(1年)
setcookie("long_term", "value", time() + (365 * 24 * 60 * 60));

// 永久Cookie(10年)
setcookie("permanent", "value", time() + (10 * 365 * 24 * 60 * 60));

// 使用mktime设置特定日期
$expiryDate = mktime(23, 59, 59, 12, 31, 2024);  // 2024年12月31日23:59:59
setcookie("new_year", "Happy New Year!", $expiryDate);

echo "各种有效期的Cookie已设置!";
?>

2. 有效期计算辅助函数

<?php
/**
 * Cookie有效期计算工具函数
 */
class CookieExpiry {
    // 单位时间秒数定义
    const MINUTE = 60;
    const HOUR = 3600;
    const DAY = 86400;
    const WEEK = 604800;
    const MONTH = 2592000;  // 30天
    const YEAR = 31536000;  // 365天

    /**
     * 计算Cookie过期时间戳
     * @param string $duration 持续时间(如:"1 hour", "30 days", "1 year")
     * @return int 过期时间戳
     */
    public static function calculate($duration) {
        $units = [
            'second' => 1,
            'minute' => self::MINUTE,
            'hour' => self::HOUR,
            'day' => self::DAY,
            'week' => self::WEEK,
            'month' => self::MONTH,
            'year' => self::YEAR,
        ];

        $pattern = '/(\d+)\s*(second|minute|hour|day|week|month|year)s?/i';

        if (preg_match($pattern, $duration, $matches)) {
            $number = (int)$matches[1];
            $unit = strtolower($matches[2]);

            if (isset($units[$unit])) {
                return time() + ($number * $units[$unit]);
            }
        }

        // 默认30天
        return time() + self::MONTH;
    }

    /**
     * 设置会话Cookie(浏览器关闭时过期)
     */
    public static function setSessionCookie($name, $value) {
        return setcookie($name, $value, 0, '/', '', false, true);
    }

    /**
     * 设置带持续时间的Cookie
     */
    public static function setCookieWithDuration($name, $value, $duration) {
        $expiry = self::calculate($duration);
        return setcookie($name, $value, $expiry, '/', '', false, true);
    }
}

// 使用示例
CookieExpiry::setSessionCookie('session_id', uniqid());
CookieExpiry::setCookieWithDuration('user_token', 'abc123xyz', '30 days');
CookieExpiry::setCookieWithDuration('remember_me', '1', '1 year');

// 手动计算
$expireTime = CookieExpiry::calculate('2 weeks');
setcookie('two_week_cookie', 'value', $expireTime);

echo "使用Cookie有效期工具函数完成设置!";
?>

Cookie安全设置

1. HttpOnly Cookie

HttpOnly标志防止JavaScript通过document.cookie访问Cookie,可以有效防止XSS攻击窃取Cookie。

<?php
// 设置HttpOnly Cookie(推荐用于会话Cookie)
setcookie(
    'secure_session',
    bin2hex(random_bytes(32)),  // 安全的随机令牌
    time() + 3600,              // 1小时后过期
    '/',                        // 整个网站
    'example.com',              // 域名
    false,                      // 不强制HTTPS(根据实际情况调整)
    true                        // HttpOnly标志
);

echo "HttpOnly Cookie已设置,JavaScript无法访问此Cookie。";
?>

2. Secure Cookie

Secure标志确保Cookie仅通过HTTPS连接传输,防止中间人攻击。

<?php
// 仅在HTTPS连接时设置Secure Cookie
if ($_SERVER['HTTPS'] === 'on' || $_SERVER['SERVER_PORT'] == 443) {
    setcookie(
        'secure_auth_token',
        bin2hex(random_bytes(16)),
        time() + 86400,  // 24小时
        '/',
        'example.com',
        true,   // Secure标志
        true    // HttpOnly标志
    );
    echo "Secure Cookie已设置(仅HTTPS)。";
} else {
    echo "警告:当前不是HTTPS连接,无法设置Secure Cookie。";
}
?>

3. SameSite属性

SameSite属性控制Cookie是否在跨站请求中发送,可以有效防止CSRF攻击。

<?php
// PHP 7.3+ 支持SameSite属性
if (PHP_VERSION_ID >= 70300) {
    // 设置SameSite=Lax(推荐默认值)
    setcookie('samesite_lax', 'value', [
        'expires' => time() + 3600,
        'path' => '/',
        'domain' => 'example.com',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Lax'
    ]);

    // 设置SameSite=Strict(更严格)
    setcookie('samesite_strict', 'value', [
        'expires' => time() + 3600,
        'path' => '/',
        'domain' => 'example.com',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Strict'
    ]);

    // 设置SameSite=None(需要配合Secure标志)
    setcookie('samesite_none', 'value', [
        'expires' => time() + 3600,
        'path' => '/',
        'domain' => 'example.com',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'None'
    ]);
}

// 对于PHP 7.2及以下版本,可以使用header()函数
if (PHP_VERSION_ID < 70300) {
    header('Set-Cookie: legacy_cookie=value; SameSite=Lax');
}

echo "SameSite Cookie属性设置完成!";
?>

4. Cookie安全最佳实践

Cookie安全指南:

  1. 使用HttpOnly标志:防止JavaScript访问敏感Cookie
  2. 使用Secure标志:确保Cookie仅通过HTTPS传输
  3. 设置适当的SameSite属性:防止CSRF攻击
  4. 限制Cookie作用域:设置正确的domain和path参数
  5. 使用合理的有效期:避免设置过长的有效期
  6. 存储最小必要数据:不要在Cookie中存储敏感信息
  7. 定期轮换Cookie:定期更新会话令牌
  8. 签名或加密Cookie数据:防止客户端篡改

实际应用示例

1. 记住我功能实现

<?php
// 登录处理
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';
    $remember = isset($_POST['remember_me']);

    // 验证用户(简化示例,实际应从数据库验证)
    if ($username === 'admin' && $password === 'password123') {
        // 创建会话
        session_start();
        $_SESSION['user_id'] = 1;
        $_SESSION['username'] = $username;

        // 如果用户选择了"记住我"
        if ($remember) {
            // 生成记住我令牌
            $token = bin2hex(random_bytes(32));
            $hashedToken = hash('sha256', $token);

            // 存储到数据库(简化示例)
            // 实际应该存储:user_id, hashed_token, expiry_date
            // $db->query("INSERT INTO remember_tokens VALUES (...)")

            // 设置Cookie(30天有效期)
            $expiry = time() + (30 * 24 * 60 * 60);
            setcookie('remember_me', $token, $expiry, '/', '', true, true);

            echo "登录成功!已启用记住我功能。";
        } else {
            echo "登录成功!";
        }
    } else {
        echo "用户名或密码错误!";
    }
}

// 检查记住我Cookie自动登录
function checkRememberMe() {
    if (!isset($_SESSION['user_id']) && isset($_COOKIE['remember_me'])) {
        $token = $_COOKIE['remember_me'];
        $hashedToken = hash('sha256', $token);

        // 从数据库验证令牌(简化示例)
        // $user = $db->query("SELECT user_id FROM remember_tokens WHERE token = ? AND expiry_date > NOW()")

        // 如果令牌有效,创建会话
        session_start();
        $_SESSION['user_id'] = 1;  // 从数据库获取的实际ID
        $_SESSION['username'] = 'admin';  // 从数据库获取的用户名

        echo "通过记住我Cookie自动登录成功!";
        return true;
    }
    return false;
}

// 页面加载时检查
checkRememberMe();
?>

2. 用户偏好设置

<?php
// 处理偏好设置表单
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_preferences'])) {
    $preferences = [
        'theme' => $_POST['theme'] ?? 'light',
        'language' => $_POST['language'] ?? 'zh-CN',
        'font_size' => $_POST['font_size'] ?? 'medium',
        'notifications' => isset($_POST['notifications']) ? true : false
    ];

    // 保存到Cookie(JSON编码)
    setcookie(
        'user_preferences',
        json_encode($preferences),
        time() + (365 * 24 * 60 * 60),  // 1年有效期
        '/',
        '',
        false,
        true
    );

    echo "偏好设置已保存!";
}

// 获取当前偏好设置
function getUserPreferences() {
    $defaults = [
        'theme' => 'light',
        'language' => 'zh-CN',
        'font_size' => 'medium',
        'notifications' => true
    ];

    if (isset($_COOKIE['user_preferences'])) {
        $preferences = json_decode($_COOKIE['user_preferences'], true);
        if ($preferences) {
            return array_merge($defaults, $preferences);
        }
    }

    return $defaults;
}

// 应用偏好设置
$prefs = getUserPreferences();

// 根据偏好设置应用样式
echo "<style>";
echo "body {";
echo "  font-size: " . ($prefs['font_size'] === 'large' ? '16px' : '14px') . ";";
if ($prefs['theme'] === 'dark') {
    echo "  background-color: #333; color: #fff;";
}
echo "}";
echo "</style>";

// 显示偏好设置表单
?>
<form method="POST">
    <h3>偏好设置</h3>
    <div>
        <label>主题:</label>
        <select name="theme">
            <option value="light" <?= $prefs['theme'] === 'light' ? 'selected' : '' ?>>浅色</option>
            <option value="dark" <?= $prefs['theme'] === 'dark' ? 'selected' : '' ?>>深色</option>
        </select>
    </div>
    <div>
        <label>语言:</label>
        <select name="language">
            <option value="zh-CN" <?= $prefs['language'] === 'zh-CN' ? 'selected' : '' ?>>简体中文</option>
            <option value="en-US" <?= $prefs['language'] === 'en-US' ? 'selected' : '' ?>>English</option>
        </select>
    </div>
    <div>
        <label><input type="checkbox" name="notifications" <?= $prefs['notifications'] ? 'checked' : '' ?>> 启用通知</label>
    </div>
    <button type="submit" name="save_preferences">保存设置</button>
</form>

3. 购物车实现

<?php
// 购物车类
class ShoppingCart {
    private $cookieName = 'shopping_cart';

    public function __construct() {
        // 初始化购物车
        if (!isset($_COOKIE[$this->cookieName])) {
            $this->saveCart([]);
        }
    }

    // 获取购物车内容
    public function getCart() {
        if (isset($_COOKIE[$this->cookieName])) {
            $cart = json_decode($_COOKIE[$this->cookieName], true);
            return $cart ?: [];
        }
        return [];
    }

    // 添加商品到购物车
    public function addItem($productId, $quantity = 1, $productData = []) {
        $cart = $this->getCart();

        if (isset($cart[$productId])) {
            $cart[$productId]['quantity'] += $quantity;
        } else {
            $cart[$productId] = [
                'quantity' => $quantity,
                'added_at' => time(),
                'data' => $productData
            ];
        }

        $this->saveCart($cart);
        return true;
    }

    // 从购物车移除商品
    public function removeItem($productId) {
        $cart = $this->getCart();

        if (isset($cart[$productId])) {
            unset($cart[$productId]);
            $this->saveCart($cart);
            return true;
        }

        return false;
    }

    // 更新商品数量
    public function updateQuantity($productId, $quantity) {
        if ($quantity <= 0) {
            return $this->removeItem($productId);
        }

        $cart = $this->getCart();

        if (isset($cart[$productId])) {
            $cart[$productId]['quantity'] = $quantity;
            $this->saveCart($cart);
            return true;
        }

        return false;
    }

    // 清空购物车
    public function clearCart() {
        $this->saveCart([]);
        return true;
    }

    // 获取购物车商品总数
    public function getTotalItems() {
        $cart = $this->getCart();
        $total = 0;

        foreach ($cart as $item) {
            $total += $item['quantity'];
        }

        return $total;
    }

    // 获取购物车总价
    public function getTotalPrice($priceList) {
        $cart = $this->getCart();
        $total = 0;

        foreach ($cart as $productId => $item) {
            if (isset($priceList[$productId])) {
                $total += $item['quantity'] * $priceList[$productId];
            }
        }

        return $total;
    }

    // 保存购物车到Cookie
    private function saveCart($cart) {
        setcookie(
            $this->cookieName,
            json_encode($cart),
            time() + (30 * 24 * 60 * 60),  // 30天有效期
            '/',
            '',
            false,
            true
        );
        $_COOKIE[$this->cookieName] = json_encode($cart);
    }
}

// 使用示例
$cart = new ShoppingCart();

// 添加商品
if (isset($_GET['add_to_cart'])) {
    $productId = $_GET['add_to_cart'];
    $cart->addItem($productId, 1, ['name' => '商品' . $productId]);
    echo "商品已添加到购物车!";
}

// 显示购物车
$cartItems = $cart->getCart();
echo "<h3>购物车 (共" . $cart->getTotalItems() . "件商品)</h3>";

if (empty($cartItems)) {
    echo "<p>购物车为空</p>";
} else {
    echo "<ul>";
    foreach ($cartItems as $productId => $item) {
        echo "<li>";
        echo "商品ID: $productId, 数量: " . $item['quantity'];
        echo " <a href='?remove_from_cart=$productId'>移除</a>";
        echo "</li>";
    }
    echo "</ul>";

    // 假设的价格列表
    $prices = [
        '1' => 100,
        '2' => 200,
        '3' => 150
    ];

    $totalPrice = $cart->getTotalPrice($prices);
    echo "<p>总价: ¥" . $totalPrice . "</p>";
}

// 清空购物车链接
echo "<p><a href='?clear_cart=1'>清空购物车</a></p>";
?>

常见问题解答

1. 为什么我的Cookie设置不生效?

可能的原因:

  • 输出在setcookie()之前:确保在调用setcookie()之前没有输出任何内容(包括空格和换行)
  • 浏览器禁用了Cookie:检查浏览器是否启用了Cookie
  • 域名或路径不匹配:检查设置的domain和path参数
  • 过期时间已到:检查设置的过期时间是否正确

2. Cookie的最大数量和大小限制是多少?

浏览器对Cookie有以下限制:

  • 数量限制:每个域名通常最多50-150个Cookie
  • 大小限制:每个Cookie通常最大4KB
  • 总大小限制:每个域名所有Cookie总和通常最大4KB
  • 有效期:通常最大为浏览器会话或设置的过期时间

3. Cookie和Session有什么区别?

主要区别:

特性 Cookie Session
存储位置 客户端浏览器 服务器端
安全性 较低(客户端可访问) 较高(仅服务器访问)
存储容量 有限(约4KB) 较大(受服务器内存限制)
生命周期 可设置长期有效 通常会话结束即销毁
性能影响 每次请求都会发送 仅存储session_id在Cookie中

4. 如何检测浏览器是否支持Cookie?

<?php
// Cookie检测函数
function checkCookieSupport() {
    if (isset($_GET['check_cookies'])) {
        if (isset($_COOKIE['cookie_test'])) {
            echo "浏览器支持Cookie!";
            setcookie('cookie_test', '', time() - 3600); // 清理测试Cookie
        } else {
            echo "浏览器可能禁用了Cookie,请启用Cookie后重试。";
        }
        exit;
    }

    // 设置测试Cookie并重定向
    setcookie('cookie_test', '1', time() + 60);
    header('Location: ' . $_SERVER['PHP_SELF'] . '?check_cookies=1');
    exit;
}

// 在需要检测的地方调用
// checkCookieSupport();
?>

Cookie兼容性和替代方案

1. 浏览器兼容性检查

<?php
/**
 * 检测浏览器Cookie支持情况的脚本
 */
function checkBrowserCompatibility() {
    echo "<script>";
    echo "if (navigator.cookieEnabled) {";
    echo "  console.log('浏览器支持Cookie');";
    echo "  document.cookie = 'js_cookie_test=1; path=/; max-age=60';";
    echo "} else {";
    echo "  console.log('浏览器不支持或禁用了Cookie');";
    echo "}";
    echo "</script>";

    // 服务器端验证
    if (isset($_COOKIE['js_cookie_test'])) {
        echo "<p class='text-success'>✓ JavaScript Cookie设置成功</p>";
    } else {
        echo "<p class='text-warning'>⚠ JavaScript Cookie设置失败</p>";
    }
}

checkBrowserCompatibility();
?>

2. Cookie的替代方案

当Cookie不可用时,可以考虑以下替代方案:

替代存储方案:

  1. URL参数:通过URL传递数据(不安全,有长度限制)
  2. 隐藏表单字段:通过表单传递数据(需要表单提交)
  3. Web Storage:localStorage和sessionStorage(HTML5)
  4. IndexedDB:客户端数据库(复杂数据存储)
  5. 服务器端Session:仅存储session_id在URL或表单中

3. 兼容性示例:Session回退方案

<?php
class SessionManager {
    private $useCookies = true;

    public function __construct() {
        // 检测Cookie支持
        $this->useCookies = $this->checkCookieSupport();

        if (!$this->useCookies) {
            $this->startSessionWithoutCookies();
        } else {
            session_start();
        }
    }

    private function checkCookieSupport() {
        // 简单的Cookie检测
        setcookie('test_cookie', '1', time() + 60);
        return isset($_COOKIE['test_cookie']) || isset($_GET['test_cookie']);
    }

    private function startSessionWithoutCookies() {
        // 使用URL传递session_id
        if (isset($_GET[session_name()])) {
            session_id($_GET[session_name()]);
        } elseif (isset($_POST[session_name()])) {
            session_id($_POST[session_name()]);
        }

        session_start();

        // 为链接和表单添加session_id
        $this->addSessionIdToUrls();
    }

    private function addSessionIdToUrls() {
        // 这个函数应该在输出HTML时被调用
        // 用于在URL中添加session_id参数
        $sessionId = session_id();

        // 可以使用输出缓冲来修改所有链接
        // 这里只是示例
    }

    public function getSessionLink($url) {
        if (!$this->useCookies) {
            $separator = (strpos($url, '?') === false) ? '?' : '&';
            return $url . $separator . session_name() . '=' . session_id();
        }
        return $url;
    }
}

// 使用示例
$session = new SessionManager();
echo "<a href='" . $session->getSessionLink('page.php') . "'>下一页</a>";
?>