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

纯PHP&MySQL构建AMP预约系统:如何限制datetime输入显示可用时段?

仅用PHP/MySQL实现AMP预约系统的时段限制方案

刚好遇到过类似的AMP环境下的预约系统需求,完全不能碰JS确实有点限制,但靠PHP和MySQL完全能搞定。先给你梳理下核心问题的解决思路,还有几个额外的实现方向:

核心问题:限制datetime输入仅显示可用时段

因为AMP禁止任何脚本,前端没法动态过滤已占用的时间,最靠谱的两种方式如下:

方案1:PHP预生成可用时段下拉列表(推荐)

直接放弃原生的datetime-local输入框,用PHP从数据库查询已预约时段,然后生成所有符合你规则的可用时段,渲染成下拉选项。用户只能选预设的可用时间,从根源避免冲突。

举个实际的代码例子,假设你的服务是工作日9:00-18:00,每小时一个时段,未来7天可预约:

<form method="post" action="your-submit-handler.php">
    <label>Service:</label>
    <select name="service">
        <?php 
        $sql = 'select c.name service from services c order by c.name'; 
        $result = $conn->query($sql); 
        if ($result->num_rows > 0) { 
            while($row = $result->fetch_assoc()) { 
                // 用htmlspecialchars防止XSS
                echo '<option>' . htmlspecialchars($row["service"]) . "</option>" ; 
            } 
        } 
        ?>
    </select>

    <br><br>

    <label>Preferred Time Slot:</label>
    <select name="date">
        <?php
        // 1. 定义你的预约规则:未来7天,工作日9-18点,每小时一个时段
        $startDate = new DateTime();
        $endDate = (new DateTime())->modify('+7 days');
        $hourlyInterval = new DateInterval('PT1H');
        $dateRange = new DatePeriod($startDate, $hourlyInterval, $endDate);

        // 2. 从requests表获取所有已预约的时段,转成统一格式方便对比
        $bookedSlots = [];
        $sql = "SELECT datetime FROM requests";
        $result = $conn->query($sql);
        if ($result->num_rows > 0) {
            while($row = $result->fetch_assoc()) {
                $bookedSlots[] = DateTime::createFromFormat('Y-m-d h:i:A', $row['datetime'])->format('Y-m-d\TH:i');
            }
        }

        // 3. 遍历生成可用时段选项
        foreach ($dateRange as $date) {
            $currentHour = (int)$date->format('H');
            // 跳过非工作时间和周末
            if ($currentHour < 9 || $currentHour >= 18 || $date->format('N') >= 6) {
                continue;
            }

            $inputValue = $date->format('Y-m-d\TH:i');
            $displayText = $date->format('Y-m-d h:i A');
            // 未被预约的时段才生成选项
            if (!in_array($inputValue, $bookedSlots)) {
                echo "<option value=\"$inputValue\">$displayText</option>";
            }
        }
        ?>
    </select>

    <br><br>

    <label>Your Name:</label>
    <input type="text" name="client" required>

    <br><br>

    <input type="submit" value="Book Now">
</form>

方案2:保留datetime-local+后端强验证

如果一定要用datetime-local输入框,可以通过PHP设置min、max和step属性引导用户选择合理范围,然后在表单提交时后端严格校验该时段是否已被占用。这种方式前端没法阻止用户选已占用的时间,但后端可以直接拒绝并返回提示。

示例表单代码:

<form method="post" action="your-submit-handler.php">
    <label>Service:</label>
    <select name="service">
        <?php 
        $sql = 'select c.name service from services c order by c.name'; 
        $result = $conn->query($sql); 
        if ($result->num_rows > 0) { 
            while($row = $result->fetch_assoc()) { 
                echo '<option>' . htmlspecialchars($row["service"]) . "</option>" ; 
            } 
        } 
        ?>
    </select>

    <br><br>

    <label>Preferred Date & Time:</label>
    <?php
    // 设置可选范围:当前时间到未来7天,步长1小时
    $minDateTime = (new DateTime())->format('Y-m-d\TH:i');
    $maxDateTime = (new DateTime())->modify('+7 days')->format('Y-m-d\TH:i');
    ?>
    <input 
        name="date" 
        type="datetime-local" 
        min="<?php echo $minDateTime; ?>" 
        max="<?php echo $maxDateTime; ?>" 
        step="3600" 
        required
    >

    <br><br>

    <label>Your Name:</label>
    <input type="text" name="client" required>

    <br><br>

    <input type="submit" value="Book Now">
</form>

对应的后端验证逻辑(your-submit-handler.php):

<?php
// 假设你已经有数据库连接$conn
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $selectedDateTime = $_POST['date'];
    $selectedService = $_POST['service'];
    $clientName = $_POST['client'];

    // 转换格式匹配数据库中的存储格式
    $formattedDateTime = DateTime::createFromFormat('Y-m-d\TH:i', $selectedDateTime)->format('Y-m-d h:i:A');

    // 检查该时段是否已被同服务预约
    $checkSql = "SELECT request_id FROM requests WHERE datetime = ? AND service_name = ?";
    $stmt = $conn->prepare($checkSql);
    $stmt->bind_param("ss", $formattedDateTime, $selectedService);
    $stmt->execute();
    $stmt->store_result();

    if ($stmt->num_rows > 0) {
        echo "<p style='color: red;'>Sorry, this time slot is already taken. Please choose another one.</p>";
    } else {
        // 插入新预约记录
        $insertSql = "INSERT INTO requests (datetime, service_name, client) VALUES (?, ?, ?)";
        $insertStmt = $conn->prepare($insertSql);
        $insertStmt->bind_param("sss", $formattedDateTime, $selectedService, $clientName);
        
        if ($insertStmt->execute()) {
            echo "<p style='color: green;'>Your booking has been confirmed successfully!</p>";
        } else {
            echo "<p style='color: red;'>Error: " . $insertStmt->error . "</p>";
        }
    }
}
?>

其他实用实现思路

  • 分步选择日期+时段:先让用户选择日期,提交后跳转到该日期的专属预约页面,PHP查询该日期的已预约时段,生成可用选项。这种分步方式更清晰,也更符合AMP的无脚本特性。
  • 适配服务时长:如果不同服务的时长不同(比如Service1是1小时,Service2是2小时),可以在services表中添加duration字段,生成可用时段时要考虑时段的占用长度,避免时间重叠(比如一个2小时的服务会占用两个连续的1小时时段)。
  • 时段锁定机制:提交预约时可以加个短暂的锁定(比如用数据库临时表),防止同一时段被多个用户同时提交(高并发场景下有用)。

内容的提问来源于stack exchange,提问作者Iustin Beceneagă

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:47:25