session_start()必须在所有输出前调用,且入口脚本首行应为;cookie_lifetime与gc_maxlifetime需一致;访问$_session键前须用isset()判断;session.save_path须确保可写。

session_start() 必须在所有输出前调用
PHP 的 $_SESSION 不是“自动可用”的全局变量,它依赖 session_start() 显式激活。一旦脚本中有任何输出(包括空格、BOM、、echo),再调用 session_start() 就会触发 “Headers already sent” 错误,导致会话完全失效。
常见错误场景:
- 在
header.php里写 HTML 开头后才调用session_start() -
home.php包含了header.php,但自己又漏掉启动会话 - 文件保存为 UTF-8 with BOM,开头隐藏字节被当成输出
正确做法:所有入口脚本(如 home.php、login.php、api.php)第一行必须是:
<?php session_start(); ?>
且该行前不能有任何字符(包括空行、空格、注释)。
cookie_lifetime 和 gc_maxlifetime 必须匹配
会话“看起来丢了”,往往不是代码问题,而是服务端和客户端对“有效期”的理解不一致。
session.cookie_lifetime 控制浏览器里 PHPSESSID Cookie 的存活时间;session.gc_maxlifetime 控制服务器上会话文件最多保留多久。如果前者是 86400(24 小时),后者却只有 1440(24 分钟),那么用户 cookie 还有效,但服务器早已删掉对应数据——结果就是 $_SESSION 为空。
建议统一设为相同值(例如 86400),并在 php.ini 或脚本开头用 session_set_cookie_params() 强制设定:
<?php session_set_cookie_params(86400, '/', '', true, true); session_start(); ?>
注意:session_set_cookie_params() 必须在 session_start() 之前调用,否则无效。
$_SESSION 键访问前必须先 isset()
直接读取未定义的键(如 $_SESSION["useruid"])会触发 Notice: Undefined index,尤其在开发环境开启 error_reporting(E_ALL) 时,可能干扰调试或暴露敏感路径。
更严重的是,is_null($_SESSION["useruid"]) 这类写法本身就有风险:未定义键会被 PHP 隐式转为 null,但这个行为不可靠,且掩盖了初始化缺失的问题。
应始终用 isset() 判断存在性:
if (!isset($_SESSION["useruid"])) {
header("Location: login.php");
exit();
}
如果需要区分 null、false、空字符串等值,再配合 array_key_exists() 或显式赋默认值。
session.save_path 权限和存储空间常被忽略
即使配置全对,$_SESSION 仍为空,大概率是写入失败。PHP 默认把会话数据存到文件系统,路径由 session.save_path 决定。
检查方法:
- 运行
echo session_save_path();查看当前路径 - 确认该目录存在,且 Web 服务器进程(如
www-data、nginx或apache)有读写权限 - 检查磁盘是否满、inode 是否耗尽(
df -i)
若使用容器或共享主机,session.save_path 可能被锁定或指向不可写位置。此时可手动指定一个可写目录:
session_save_path("/tmp/php_sessions");
mkdir -p /tmp/php_sessions;
chmod 700 /tmp/php_sessions;
这个路径必须在 session_start() 前设置,且确保所有请求都使用同一路径(否则会话无法跨页恢复)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











