
本文介绍如何通过 php session 解决任务数组仅显示最新一条的问题,实现多任务累积存储与展示,避免每次刷新或提交后数据丢失。
本文介绍如何通过 php session 解决任务数组仅显示最新一条的问题,实现多任务累积存储与展示,避免每次刷新或提交后数据丢失。
在当前的 PHP 日历任务系统中,每次提交新任务时,$tasks 数组都是重新初始化的单元素数组:
$tasks = array(
array('name' => '$task_name', 'day' => $day, 'month' => $month, 'year' => $year)
);由于该数组未保留历史数据,且未做任何持久化处理,因此页面每次加载都只显示当前请求携带的那一个任务——这就是“只显示最后一条任务”的根本原因。
✅ 正确做法是:将任务追加到可跨请求保持的数据容器中。PHP 的 $_SESSION 是最轻量、安全且无需额外配置的首选方案(相比数据库或 Cookie/LocalStorage,它服务端存储、不易篡改、天然支持结构化数据)。
✅ 实现步骤详解
-
开启 Session:在文件顶部(任何输出前)调用
session_start(); -
接收并验证任务参数:使用
isset()安全检查$_GET['task_name']等字段是否存在; -
追加任务到 Session 数组:使用
$_SESSION['tasks'][] = [...]语法自动推入新任务; -
渲染全部任务:遍历
$_SESSION['tasks']输出表格行,而非仅渲染当前 GET 参数。
以下是关键代码段优化说明(已整合进完整流程):
立即学习“PHP免费学习笔记(深入)”;
<?php
session_start(); // ⚠️ 必须放在最开头,且不能有任何输出(包括空格、BOM)
// ...(日历生成逻辑保持不变)...
// ✅ 安全接收并存储新任务(仅当参数齐全时执行)
if (isset($_GET['task_name'], $_GET['day'], $_GET['month'], $_GET['year'])) {
$task_name = htmlspecialchars($_GET['task_name']); // 防XSS,推荐添加
$day = (int)$_GET['day'];
$month = (int)$_GET['month'];
$year = (int)$_GET['year'];
$_SESSION['tasks'][] = [
'name' => $task_name,
'day' => $day,
'month' => $month,
'year' => $year
];
}
// ✅ 渲染所有已存任务
echo "<h2>Tasks</h2>";
echo "<table><tr><th>Task Name</th><th>Date</th></tr>";
if (!empty($_SESSION['tasks'])) {
foreach ($_SESSION['tasks'] as $task) {
echo "<tr>";
echo "<td>" . htmlspecialchars($task['name']) . "</td>";
echo "<td>{$task['day']}/{$task['month']}/{$task['year']}</td>";
echo "</tr>";
}
} else {
echo "<tr><td colspan='2'>No tasks yet. Click a date to add one!</td></tr>";
}
echo "</table>";
?>⚠️ 注意事项与最佳实践
-
Session 初始化时机:
session_start()必须在任何 HTML 输出或空白字符之前调用,否则会报错 “Headers already sent”; -
安全性增强:对用户输入(如
$_GET['task_name'])使用htmlspecialchars()转义,防止 XSS 攻击; -
类型安全:对数字型参数(
day/month/year)强制转换为(int),避免意外字符串注入; -
空状态友好:检查
!empty($_SESSION['tasks'])再循环,避免警告;提供默认提示提升体验; - 长期方案建议:Session 数据随浏览器关闭或超时而丢失。如需长期保存(如多设备同步、历史追溯),应升级为 MySQL 或 SQLite 数据库存储,并配合表单 POST + CSRF 保护。
通过以上改造,你的日历应用即可稳定支持多任务添加与回显——无需数据库,开箱即用,兼顾简洁性与实用性。



















