← PHP文件包含机制:include与require的选型逻辑与实战细节 PHP Session会话管理:跨页面数据传递的核心机制 →

PHP Cookie机制:从设置、读取到安全删除的操作

原创 2026-05-11 PHP 已有人查阅

HTTP协议本身是无状态的,服务器处理完一个请求后,不会记得上一个请求是谁发的。这给需要保持登录状态、记住用户偏好的 Web 应用带来了难题。PHP Cookie就是解决这个“记忆断层”的工具——服务端在用户浏览器里存一小段数据,下次请求时浏览器自动带回,服务器就能认出这个用户。

简单说,Cookie由服务端生成,通过HTTP响应头发送给浏览器,浏览器存下来,后续每次请求该域名时自动携带,服务器通过 $_COOKIE 超全局数组读取。

有个重要的前提:setcookie() 函数必须在任何实际输出之前调用,包括HTML标签和空格。因为设置Cookie本质上是发送 HTTP头,而 HTTP头必须在响应体之前送达。如果已经 echo 了内容再调 setcookie(),函数直接返回 false,Cookie设置失败。这个坑我早年排查了半天,日志里没报错,但 Cookie死活写不进去,之后发现是文件开头有个 UTF-8 BOM 头提前输出了。

PHP setcookie() 函数的参数拆解

setcookie() 函数负责往浏览器写入 Cookie。完整语法如下:

bool setcookie (
    string $name,
    string $value = "",
    int $expire = 0,
    string $path = "",
    string $domain = "",
    bool $secure = false,
    bool $httponly = false
)

一个个拆开看:

$name 是 Cookie的名字,必填项。取名时注意别跟其他 Cookie冲突,尤其不要用中文或特殊符号。

$value 是存放的数据,字符串类型。存复杂数据时可以用 json_encode() 编码后存入,取出来再 json_decode()

$expire 是过期时间的 Unix 时间戳。设为 0 或者不填,Cookie会在浏览器关闭时自动消失,这叫会话 Cookie。设一个未来时间,就是持久 Cookie,浏览器关掉再打开还在。time() + 86400 表示从现在起 24 小时后过期。

$path 限定 Cookie在网站的哪些路径下可用。设为 / 表示整站有效;设 /course/ 则只有课程相关路径才能拿到这个 Cookie。

$domain 限定域名范围,一般留空就行,留空默认当前域名。

$secure 设为 true 时,Cookie只在 HTTPS 连接下传输。生产环境尽可能开启。

$httponly 设为 true 时,JavaScript 的 document.cookie API 无法读取这个 Cookie,能有效降低跨站脚本攻击窃取 Cookie的风险。存放登录令牌的 Cookie强烈建议开启这项。

示例先行,比光看参数理解得快:

// 最简用法,浏览器关了就消失
setcookie("site_name", "编程实训平台");

// 1 小时后过期
setcookie("login_user", "小明", time() + 3600);

// 24 小时后过期,限定路径,HTTPS 传输,JS 不可读
setcookie("auth_token", "abc123xyz", time() + 86400, "/", "", true, true);

第三个示例的写法适合存放敏感凭据。我在项目里往往把 access token 放在 $httponly 开启的 Cookie里,前端 JavaScript 不用直接碰这个 Cookie,所有 API 鉴权由服务端通过 Cookie完成,安全边界更清晰。

PHP $_COOKIE:读取客户端带回的 Cookie

Cookie设置成功后,浏览器下次访问时自动携带,PHP 用 $_COOKIE 超全局数组接收。取值方式和普通数组一样。

创建 Cookie的脚本和使用 Cookie读取的脚本通常是同一个或同域下的配合。需要注意一个时序问题:setcookie() 在当前请求执行完后,Cookie才被写入浏览器。也就是说,同一请求内设置 Cookie后立刻用 $_COOKIE 读取是拿不到的,必须等下一次页面加载。

编写 cookie_set.php:

<?php
setcookie("student", "李四", time() + 3600);
echo "Cookie 已设置,刷新页面查看效果。";
?>

编写 cookie_read.php:

<html>
<body>
<?php
if (!isset($_COOKIE['student'])) {
    echo "暂时没找到名为 student 的 Cookie。";
} else {
    echo "student Cookie 的值为:" . htmlspecialchars($_COOKIE['student']);
}
?>
</body>
</html>

首次加载 cookie_read.php 时因为 Cookie还没被浏览器带回,会显示“暂时没找到”。设置完 cookie_set.php 后再访问 cookie_read.php,就能读到“李四”。有些新手会困惑为什么设置了却读不到,原因就在于这个时序——不是代码写错了,而是 Cookie天生需要一次往返。

结合 null 合并运算符 ??,可以优雅地处理 Cookie不存在时的默认值:

$theme = $_COOKIE['theme'] ?? 'light';
echo "当前主题模式:" . htmlspecialchars($theme);

这个写法在首次访问且 Cookie未设置时不会报 undefined index 的警告,比 isset() 嵌套三元运算符简洁不少。

删除 Cookie:把过期时间调到过去

PHP 没有专门的“删除 Cookie”函数。删除的本质是把同一个 Cookie的过期时间设置成过去的时间,浏览器发现它已过期,就会从本地存储中移除。

// 把过期时间设为 1 小时前
setcookie("student", "", time() - 3600);

参数里名字必须和要删除的 Cookie一致,value 可以留空。path 和 domain 也得一致,否则浏览器可能认为这是两个不同的 Cookie,导致删除不成功。之前我遇到过一个诡异情况,子目录下的 Cookie在根目录删不掉,排查后发现就是 path 参数没对齐。

完整演示一下创建和删除的流程,编写 cookie_lifecycle.php:

<?php
if (isset($_POST['action'])) {
    if ($_POST['action'] === 'set') {
        setcookie("temp_user", "王五", time() + 600); // 10 分钟后过期
        $msg = "Cookie 已创建。";
    } elseif ($_POST['action'] === 'delete') {
        setcookie("temp_user", "", time() - 3600);
        $msg = "Cookie 已删除。";
    }
}
?>
<html>
<body>
    <form method="POST">
        <button name="action" value="set">设置 Cookie</button>
        <button name="action" value="delete">删除 Cookie</button>
    </form>
    <p>
        <?php
        echo $msg ?? '';
        echo '<br>当前 Cookie 值:' . ($_COOKIE['temp_user'] ?? '无');
        ?>
    </p>
</body>
</html>

点击“设置 Cookie”,刷新后页面显示“王五”。点击“删除 Cookie”,再刷新,值就变回“无”。这个例子把设置、读取、删除串成一条完整的操作链,初学时照着敲一遍对 Cookie生命周期就有直观认识。

场景化实战:记住用户名功能

很多网站登录页有个“记住我”复选框,原理就是 Cookie持久化。简单实现如下。

login_remember.php:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'] ?? '';
    $remember = isset($_POST['remember']);
    
    if ($remember) {
        // 记住 7 天
        setcookie("saved_username", $username, time() + 7 * 86400, "/", "", false, false);
    } else {
        setcookie("saved_username", "", time() - 3600, "/");
    }
    echo "登录成功," . htmlspecialchars($username);
}
?>
<html>
<body>
    <form method="POST">
        <input type="text" name="username" placeholder="请输入用户名"
               value="<?php echo htmlspecialchars($_COOKIE['saved_username'] ?? ''); ?>">
        <label><input type="checkbox" name="remember"> 记住我</label>
        <button type="submit">登录</button>
    </form>
</body>
</html>

下一次打开页面时,输入框自动填上之前保存的用户名。这里 Cookie没放敏感信息,所以 $secure 和 $httponly 都没开启,$httponly 关闭才能让 JavaScript 读到,不过这里直接用 PHP 回填到 input 里,实际也没必要让 JS 碰它。

本节课程知识要点

Cookie的操作围绕 setcookie() 写入和 $_COOKIE 读取展开。设置 Cookie必须在页面输出之前完成,否则发送 HTTP头失败;$expire 控制生命周期,0 为会话级、大于 0 为持久级;$httponly 标志能切断 JavaScript 对 Cookie的访问通道,对存放身份凭证的 Cookie很重要;删除 Cookie的本质是将过期时间设为过去,且 path、domain 参数必须与创建时一致。Cookie存储量有限,单个不超过 4KB,也不宜存放过多数据内容,大段信息应交给服务端 session 或数据库管理。时序上,setcookie() 写入的数据当前请求内 $_COOKIE 不会立即反映,必须下次请求才能拿到,这个异步特性写逻辑时要时刻留意。

← PHP文件包含机制:include与require的选型逻辑与实战细节 PHP Session会话管理:跨页面数据传递的核心机制 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号