You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL LIKE语句在复选框组合字段匹配时失效的技术求助

嘿,我来帮你搞定这个申请系统的日期冲突校验问题!

首先得明确你现在遇到的核心问题:你用LIKE '%$chk%'的匹配逻辑完全不符合需求——它只会匹配那些完全包含你新提交的整个day字符串的记录,但你实际需要的是「新申请的任意一个日期和已有记录的任意一个日期重叠就拒绝」。另外你生成$chk的方式会在末尾多一个空格,也会导致匹配异常。

第一步:修复day字段的存储格式

先把生成day字符串的代码改得更规范,去掉多余的末尾空格,用统一的分隔符(比如逗号+空格)来存储多个日期:

$days = $_POST['day'];
// 生成格式统一的字符串,比如 "Rabu, KHamis, Jumaat"
$day_str = implode(', ', $days);

第二步:修改冲突校验的SQL逻辑

不能再用单个LIKE来匹配整个字符串了,要针对每个选中的日期,检查它是否存在于已有记录的day字段中。这里给你两种可靠的实现方式:

方式一:精确匹配(推荐,避免部分匹配错误)

针对每个日期,构造条件匹配它在day字段的开头、中间、结尾或者作为单个值的情况,避免出现比如"Rabu"误匹配"Rabu1"的问题:

$day_conditions = [];
foreach($days as $day) {
    // 覆盖所有可能的出现位置
    $day_conditions[] = "day LIKE '$day,%' OR day LIKE '%, $day,%' OR day LIKE '%, $day' OR day = '$day'";
}
$day_condition = implode(' OR ', $day_conditions);

// 替换原SQL中的day匹配部分
$sql = "SELECT * FROM job 
        WHERE start <= '$end' 
          AND fetchEnd >= '$start' 
          AND location = '$lokasi' 
          AND timeStart <= '$timeEnd' 
          AND timeEnd >= '$timeStart' 
          AND ($day_condition) 
        LIMIT 1";

方式二:改用纯逗号分隔存储,用FIND_IN_SET简化逻辑

如果把存储格式改成纯逗号分隔(比如"Rabu,KHamis,Jumaat"),可以用MySQL的FIND_IN_SET函数让代码更简洁:

// 存储时改用纯逗号分隔
$day_str = implode(',', $days);

// 构造查询条件
$day_conditions = [];
foreach($days as $day) {
    $day_conditions[] = "FIND_IN_SET('$day', day)";
}
$day_condition = implode(' OR ', $day_conditions);

$sql = "SELECT * FROM job 
        WHERE start <= '$end' 
          AND fetchEnd >= '$start' 
          AND location = '$lokasi' 
          AND timeStart <= '$timeEnd' 
          AND timeEnd >= '$timeStart' 
          AND ($day_condition) 
        LIMIT 1";

第三步:必须修复SQL注入漏洞!

你现在的代码直接把用户输入拼到SQL里,非常容易被黑客攻击,一定要用mysqli的预处理语句绑定参数。这里给你完整的安全实现示例(以精确匹配为例):

// 获取并整理参数
$days = $_POST['day'];
$end = $_POST['end'];
$start = $_POST['start'];
$lokasi = $_POST['lokasi'];
$timeEnd = $_POST['timeEnd'];
$timeStart = $_POST['timeStart'];

// 构造查询条件和参数数组
$day_conditions = [];
$params = [$end, $start, $lokasi, $timeEnd, $timeStart];
$types = 'sssss'; // 对应前面5个字符串参数

foreach($days as $day) {
    $day_conditions[] = "(day LIKE ? OR day LIKE ? OR day LIKE ? OR day = ?)";
    // 添加当前日期的4种匹配参数
    $params[] = "$day,%";
    $params[] = ", $day,%";
    $params[] = ", $day";
    $params[] = $day;
    $types .= 'ssss';
}
$day_condition = implode(' OR ', $day_conditions);

// 执行预处理查询
$sql = "SELECT * FROM job 
        WHERE start <= ? 
          AND fetchEnd >= ? 
          AND location = ? 
          AND timeStart <= ? 
          AND timeEnd >= ? 
          AND ($day_condition) 
        LIMIT 1";

$stmt = mysqli_prepare($con, $sql);
mysqli_stmt_bind_param($stmt, $types, ...$params);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$count_valid = mysqli_num_rows($result);

// 后续的判断和插入逻辑也要用预处理!
if ($count_valid > 0) {
    echo "<script> alert('Permohonan anda gagal kerana bertindih dengan tarikh / masa / lokasi mesyuarat lain. Sila semak Kalendar Perkhidmatan Sidang Video.'); window.location.href = 'mohon.php';</script> ";
} else {
    $day_str = implode(', ', $days);
    // 插入数据的预处理示例
    $insert_sql = "INSERT INTO job (title, start, end, department, fetchEnd, location, day, timeStart, timeEnd, kekerapan, communication, promoter, typeMeeting, status, employId) 
                   VALUES (?, ?, DATE_ADD(?, INTERVAL 1 DAY), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
    $insert_stmt = mysqli_prepare($con, $insert_sql);
    mysqli_stmt_bind_param($insert_stmt, "sssssssssssssss", $title, $start, $end, $bahagian, $end, $lokasi, $day_str, $timeStart, $timeEnd, $kekerapan, $komunikasi, $penganjur, $sulit, $status, $id);
    mysqli_stmt_execute($insert_stmt);
}

为什么原来的方法不行?

你之前的LIKE '%$chk%'是检查已有记录的day字段是否包含整个新提交的day字符串——比如新申请是"Rabu",已有记录是"Rabu, KHamis",如果$chk带末尾空格,LIKE '%Rabu %'能匹配到,但如果新申请是"Rabu, KHamis",已有记录是"Rabu",那LIKE '%Rabu, KHamis%'就完全匹配不到,这完全不符合「任意日期重叠就拒绝」的需求。

内容的提问来源于stack exchange,提问作者SYAMIL BIN YUSRI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 01:53:13