PHP实现echo消息div封装及HTML5日期选择器屏蔽周末节假日方法
解答
1. 如何将提示信息放入可自定义样式的div容器
实现逻辑非常简单,不要在流程分支里直接零散echo提示内容,先把提示内容和类型存到PHP变量里,最后在按钮下方的固定位置输出套好对应class的div即可,后续写CSS直接针对class控制样式。
修改后的核心代码示例:
<?php // 初始化提示变量 $alert = ''; if ($_SERVER['REQUEST_METHOD']=='POST') { // 先处理表单action的XSS防护,这行你原来写了但没用到 $formAction = htmlspecialchars($_SERVER["PHP_SELF"]); $name = trim($_POST["name"]); $email = trim($_POST["email"]); $phone = trim($_POST["phone"]); $date = trim($_POST["date"]); $time = trim($_POST["time"]); if (!empty($name) && !empty($email) && !empty($phone) && !empty($date) && !empty($time)) { $host = "localhost"; $dbname = "appointments"; $username = "root"; $password = ""; $conn = mysqli_connect($host, $username, $password, $dbname); if (mysqli_connect_errno()){ // 线上环境不要直接输出数据库错误,改成通用提示,错误写日志 $alert = '<div class="alert error">系统繁忙,请稍后重试</div>'; } else { $sql = "INSERT INTO appuntamenti (name, email, phone, date, time) VALUES(?, ?, ?, ?, ?)"; $stmt = mysqli_stmt_init($conn); if (!mysqli_stmt_prepare($stmt, $sql)) { $alert = '<div class="alert error">提交失败,请稍后重试</div>'; } else { mysqli_stmt_bind_param($stmt, "sssss", $name, $email, $phone, $date, $time); if (mysqli_stmt_execute($stmt)) { // 成功后重定向,防止刷新重复提交 header("Location: ".$_SERVER['PHP_SELF']."?success=1"); exit; } else { $alert = '<div class="alert error">提交失败,请稍后重试</div>'; } mysqli_stmt_close($stmt); } mysqli_close($conn); } } else { $alert = '<div class="alert error">请填写所有必填字段</div>'; } } // 处理重定向回来的成功提示 if (isset($_GET['success']) && $_GET['success'] == 1) { $alert = '<div class="alert success">预约提交成功,我们会尽快与您联系</div>'; } ?> <!-- 表单部分 --> <form method="POST" action="<?= $formAction ?? htmlspecialchars($_SERVER['PHP_SELF']) ?>"> <!-- 这里放你的name、email、phone、date、time输入框 --> <button class="btn" type="submit">Submit</button> <!-- 固定位置输出提示 --> <?= $alert ?> </form>
对应的CSS样式可以直接按需求写,示例:
.alert { padding: 12px 16px; margin: 16px 0; border-radius: 4px; border: 1px solid transparent; /* 要加图标的话可以用background-image配置图标路径 */ } .alert.success { background-color: #d4edda; border-color: #c3e6cb; color: #155724; } .alert.error { background-color: #f8d7da; border-color: #f5c6cb; color: #721c24; }
2. 原生datepicker屏蔽周末、节假日的实现方案
首先明确一个限制:原生HTML5 <input type="date"> 控件没有提供传入禁用日期列表的属性,纯PHP(不借助前端JS)无法在日期选择面板里直接把周末、节假日灰化禁止点击,因为PHP是服务端语言,页面渲染完成后无法控制浏览器原生控件的交互行为。
纯PHP可以实现的稳妥方案是做两层处理:
- 给日期输入框设置合理的可选范围,减少用户选错的概率
- 表单提交时做严格后端校验,拦截周末、节假日的预约请求,返回对应错误提示
代码示例:
<?php // 提前配置当年法定节假日,格式为Y-m-d,每年更新一次即可 $holidays = [ '2024-10-01', '2024-10-02', '2024-10-03', '2024-10-04', '2024-10-05', '2024-10-06', '2024-10-07', // 其他节假日自行补充 ]; $minDate = date('Y-m-d'); // 最多支持预约未来30天的号 $maxDate = date('Y-m-d', strtotime('+30 days')); // 提交时的日期校验逻辑,放在字段非空判断之后 if (!empty($date)) { $dateStamp = strtotime($date); $weekDay = date('w', $dateStamp); // 周日返回0,周六返回6 // 校验是否为周末 if ($weekDay == 0 || $weekDay == 6) { $alert = '<div class="alert error">周末暂不支持预约,请选择工作日</div>'; } // 校验是否为节假日 else if (in_array($date, $holidays)) { $alert = '<div class="alert error">所选日期为法定节假日,暂不支持预约</div>'; } // 校验是否在可选范围内 else if ($date < $minDate || $date > $maxDate) { $alert = '<div class="alert error">所选日期不在可预约范围内</div>'; } } ?> <!-- 日期输入框 --> <input type="date" name="date" min="<?= $minDate ?>" max="<?= $maxDate ?>" required>
如果需要做到用户在日期面板里直接点不了周末/节假日,必须加少量前端JS配合,纯PHP无法实现这个前端交互效果。另外注意:所有前端限制都可以被用户通过浏览器控制台绕过,后端校验是必须做的,不能省略。
现有代码的问题与优化方向
- 安全问题:你虽然用了mysqli预处理语句防SQL注入,但没有对用户输入做格式校验,比如邮箱格式、手机号格式、日期合法性都没判断,非法数据也能存入数据库;另外输出用户输入内容时没有用
htmlspecialchars()转义,存在XSS攻击风险;数据库连接出错时直接die()输出原始错误,线上环境会泄露数据库等敏感信息,应该返回通用提示,把详细错误记录到服务端日志。 - 语法问题:原来的成功提示
echo "<Booking was successful"存在语法错误,开头的<会被浏览器识别为HTML标签,且标签未闭合,会导致输出乱码。 - 无用代码:你写的
htmlspecialchars($_SERVER["PHP_SELF"]);没有赋值也没有输出,完全不生效,正确用法是放到form标签的action属性里做XSS防护。 - 体验问题:表单校验失败后用户之前填的内容会全部清空,建议把用户提交的内容转义后回填到对应输入框的value属性里,减少用户重复输入成本;提交成功后没有做重定向,用户刷新页面会重复提交表单,造成重复预约。
- 资源释放问题:数据库操作完成后没有关闭连接、释放预处理语句,小流量场景影响不大,流量上来后可能耗尽数据库连接。
- 逻辑漏洞:没有捕获数据库执行失败的场景(比如SQL错误、字段冲突),出错时用户会看到白屏或PHP报错,没有友好提示。
- 日期限制不完善:只设置了最小日期为当天,没有设置最大可预约日期,用户可以选几年后的日期,不符合预约业务的实际需求。
内容的提问来源于stack exchange,提问作者PezziXXVII
相关产品推荐
相关产品推荐

