0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHPで予約表を作成

Last updated at Posted at 2025-07-11

概要

某大手予約サイトのような、予約時の日時選択画面を作成しました。
横軸に当日から1週間の日付、縦軸に30分間隔で営業時間帯の時刻表示がされます。
DBから取得した情報をもとに、予約可能な箇所には「◎」、すでに予約が入っていたり定休日で予約できない場合には「×」を表示しています。
下記サイトののカレンダー作成方法を参考に、アレンジ加えて作成しました。
(https://codeforfun.jp/php-calendar/)

実際の画面

スクリーンショット 2025-07-11 101234.png


コード

  • PHP
date_reserve.php
<?php session_start(); ?>
<?php require('./dbconnect.php'); ?>
<?php
$youbiarray = [
  '日', //0
  '月', //1
  '火', //2
  '水', //3
  '木', //4
  '金', //5
  '土', //6
];

//POSTされた情報を整形して変数に格納
if(isset($_REQUEST['rdate'])){
  $rdate = $_REQUEST['rdate'];
  $date = date('Y年n月j日',strtotime($rdate)).'('.$youbiarray[date('w',strtotime($rdate))].')';
} else {
  $rdate = null;
}

//今月の日付 フォーマット 例)2020-10-2
if (!isset($rdate)){
  $today = date('Y-n-j');
} else {
  $today = $rdate;
}
$dttoday = new DateTime($today);
$dttoday2 = new DateTime($today);
//前週・次週の月日を取得
//1週間前
$sprev = $dttoday2->modify('-1 week');
$prev = $sprev->format('Y-n-j');
//1週間後(直前のmodifyで-1week しているので、+2weekする)
$snext = $dttoday2->modify('+2 week');
$next = $snext->format('Y-n-j');
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="css/style.css">
  
</head>
  <body>
    <section id="reserve">
      <div class="reserve-section">
      <?php
        //時間選択
        $sql=$db->prepare('SELECT r.res_date, r.comp_date FROM reserve r 
                            WHERE r.res_date >= ?'); //DBから予約日時と席が空く時間を取得
        $sql->bindparam(1,$today); //本日以降
        $sql->execute();
        $result = $sql->fetchALL();
        
        $i=0;
        
        if (isset($result)){
          foreach ($result as $row){
            $resdata[$i] = explode(" ",$row['res_date']);
            $hoge = explode(" ",$row['comp_date']);
            $resdata[$i][2] = $hoge[1];
            $i++;
          }
          if(isset($resdata)){
            $_SESSION['yoyaku'] = $resdata; //画面遷移時のため、SESSIONに保存 
          }
        }
        ?>

        
        <div class="reserve-box">      
          <div class="calender">
            <?php
            //1週間ことの情報を画面表示
            if (!isset($rdate) || $rdate === date('Y-n-j')){ //本日以前は表示させない
              echo '<h3><font color="white">&lt;&nbsp;前の週</font> 次の週<a href="?rdate='. $next .'">&nbsp;<font color="white">&gt;</font></a></h3>';
            } else {
              echo '<h3><a href="?rdate='. $prev .'"><font color="white">&lt;</font>&nbsp;</a>前の週 次の週<a href="?rdate=' .$next .'">&nbsp;<font color="white">&gt;</font></a></h3>';
            }
            ?>
            
            <table class="table table-bordered">        
              <tr>
                <th></th>
                
                <?php
                //1週間分の日付表示
                for ($i=0; $i<=6; $i++){
                  if ($dttoday->format("w") === "0") {
                    echo '<th class="calender-date sunday">'.$dttoday->format("n月j日").'('.$youbiarray[$dttoday->format("w")].')</th>';
                  } else if ($dttoday->format("w") === "6"){
                    echo '<th class="calender-date saturday">'.$dttoday->format("n月j日").'('.$youbiarray[$dttoday->format("w")].')</th>';
                  } else {
                    echo '<th class="calender-date">'.$dttoday->format("n月j日").'('.$youbiarray[$dttoday->format("w")].')</th>';
                  }
                  $dttoday->modify("+1 day");
                }
                ?>
              </tr>


              <!-- 各日付、時間帯ごとの予約状況表示 -->
              <?php
              //XX:30の時刻表示用変数
              $thirty = false;
              $i = 9;
              while ($i<=18) { //18時まで表示
                $dttoday = new DateTime($today);
                echo '<tr>';
                for ($n=0; $n<=7; $n++){ //7日分
                  if ($n===0){ //n===0の時は時刻表示
                    if ($thirty && $i === 18) { //18:00で表示を止めるための処理
                      $i++;
                      break;
                    } else if ($thirty) { //XX:30の時刻表示用変数
                      $reservetime = sprintf('%02d',$i) . ':30';
                      echo '<td>'.$reservetime.'</td>';
                      $thirty = false;
                      $i++;
                    } else { //XX:00の時刻表示用変数
                      $reservetime = sprintf('%02d',$i) . ':00';
                      echo '<td>'.$reservetime.'</td>';
                      $thirty = true;
                    }
                    
                  } else { //n!==0の時はボタンを表示
                    $flag = true;
                    if (isset($_SESSION['yoyaku'])){
                      foreach ($_SESSION['yoyaku'] as $row){
                        if ($dttoday->format('Y-m-d') == $row[0]){
                          if ($reservetime >= substr($row[1],0,5) && $reservetime <= substr($row[2],0,5)){
                            $flag = false;
                          }
                        }
                      }
                    }
                    
                    if ($dttoday->format("w") === "3"|| ((!$flag))) { //水曜時はボタンを非表示
                      echo '<td>×</td>';
                    } else { //ボタン表示してデータをPOST
                      echo '<td><form method="post" action="###">';
                      echo '<input type="hidden" name="rtime" value="'.$reservetime.'">';
                      echo '<button type="submit" name="rdate" value="'.$dttoday->format('Y-m-j').'">◎</button>';
                      echo '</form></td>';
                    }
                    $dttoday->modify('+1 day');
                  }
                }
                echo '</tr>';
              }
              ?>
            </table>
          </div>   
        </div>
      </div>
    </section>
    <footer></footer>
  </body>
</html>

1行目
初回表示時は$todayに本日の日付をいれ、1週間分の日付表示。
1週間前、1週間後の月日を取得し、「前の週」「次の週」をクリック時には該当のデータを$todayにいれ、表示する日付を変更。

2行目以降
1列目には時刻を表示。
時刻の分表示は 30 と 00 を$thirtyで管理し1行表示ごとに切替。

2~8行目にはボタンを配置。
ボタンひとつひとつに、該当する日付と時刻がPOSTされるようになっています。
DBからdatetime型の予約開始時間と予約終了時間を取得して、その範囲内にあれぱボタンではなく「×」が表示されます。


  • CSS
style.css
 :root {
      --bg: #0d0d0d;
      --text: #eee;
      --card-bg: rgba(255, 255, 255, 0.05);
      --accent: #d1bfa3;
      --shadow: rgba(0, 0, 0, 0.5);
      --radius: 16px;
    }

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      font-family: 'Noto Sans JP', sans-serif;
      background-color: var(--bg);
      color: var(--text);
      line-height: 1.7;
    }

    section {
      padding: 100px 20px;
      max-width: 1200px;
      margin: 0 auto;
    }

    /* --- 予約-メニュー選択 --- */
    .reserve-box h3 {
      font-family: 'Playfair Display', serif;
      font-size: 2rem;
      margin-bottom: 30px;
      color: var(--accent);
    }
    
    .reserve-box button {
      font-family: 'Playfair Display', serif;
      font-size: 2rem;
      width: 120px;
      border-radius: 10px 10px 10px 10px;
      color:#000;
      background-color: var(--accent);
      align-items: center;
    }

    /* --カレンダー-- */
    .calender a {
        text-decoration: none;
    }
    .calender table {
        color:#000;
        background-color: #fff;
        border-width: 0.5rem;
        table-layout: fixed;
        width: 90%;
        margin:auto;
    }
    .calender th {
      height: 30px;
      text-align: center;
    }
    .calender td {
      height: auto;
      text-align: center;
    }
    .calender button {
      height: auto;
      width: 100%;
      border: transparent;
      background: transparent;
    }
    .calender-date {
      width:12%;
    }
    .sunday  {
      color:red !important;
    }
    .saturday {
      color:blue!important;
    }
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?