0%

[技能檢定]題組三 步驟16 前台線上訂票功能-電影及場次選擇

線上訂票功能我們分兩部份來製作,一個是電影選擇的功能,一個是劃位及完成訂票的功能,這邊主要都是使用ajax來完成的,所以重點放在如何取得前端的資料並傳送給後端去做處理,相較題組一二的ajax功能,這邊使用到的ajax複雜度提升不少。

由於題組三會使用到時間的計算,而php預計的時區和台北這邊差了八小時,除了可以在php.ini中設定系統時區外,也可以直接在程式中下指令來設定程式執行期間的時區;
db.php

1
2
//設定時區
date_default_timezone_set("Asia/Taipei");

建立訂單畫面

  1. 建立 /front/order.php 檔案,並撰寫基本的頁面html碼,這邊我們會建立三個下拉選單的項目,但是選項內容可以先空著,選單中的下拉選項會全部由ajax的方式從後端來取得,這邊的CSS美化都可以晚點再做,先把畫面該有的元素及功能完成即可
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!--建立一個容器用來放置訂票選單-->
    <div id='select'>
    <h3 class="ct">線上訂票</h3>
    <div class="order">
    <div>
    <label>電影:</label>
    <select name="movie" id="movie">
    </select>
    </div>
    <div>
    <label>日期:</label>
    <select name="date" id="date"></select>
    </div>
    <div>
    <label>場次</label>
    <select name="session" id="session"></select>
    </div>
    <div>
    <button>確定</button>
    <button>重置</button>
    </div>
    </div>
    </div>

建立頁面互換機制

由於題目要求在劃位畫面的上一步功能回到訂票選單時要保留原本的選單狀況,如果使用cookie、session、GET、POST等方法來傳遞狀態,會比較花時間,考量時間解題時間有限的狀況下,我們透過js來控制區塊的呈現,這樣就只要切換畫面就可以了,不用去處理選單的狀態

1
2
3
4
5
6
7
8
9
<div id="select">
......
<input type="button" value="確定" onclick="$('#select,#booking').toggle()">
<input type="reset" value="重置">
</div>
<div id="booking" style="display:none">
<button onclick="$('#select,#booking').toggle()">上一步</button>
<button>訂購</button>
</div>

建立ajax取得選單資料函式

由於三個選單是互有關聯的,因此我們需要建立三個函式來取得選單的資料,並且讓函式可以透過指定參數來取得內容

  1. 解析網址參數,有兩種做法,前端js的方法和後端php的做法,目的是取得從院線片的 線上訂票 按鈕轉址過來時,網址中的 id 這個參數

    1
    2
    3
    4
    5
    6
    //利用URL API建立目前的網址物件
    let url=new URL(window.location.href)

    //使用PHP來取得網址參數
    //let id=<?=$_GET['id']??0;?>;

  2. 取得所有上映電影的函式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //取得可訂票院線片清單
    function getMovies(){
    //以ajax的請求去取得目前所有上映中的影片
    $.get("./api/get_movies.php",(movies)=>{
    //將影片的選項放到#movie的選單中
    $("#movie").html(movies);

    /**
    * 判斷網址中是否有id這個參數在
    * 如果有,表示是從某部電影按下訂票按鈕來的
    * 如果沒有,表示是直接點下主選項中的電影訂票連結來的
    */
    if(url.searchParams.has('id')){
    //如果網址中帶有id,則將選單定位到該部電影的選項中
    $(`#movie option[value='${url.searchParams.get('id')}']`).prop('selected',true);
    }

    //將電影選單中的值帶入到getDate()函式中,去執行可上映日期選單的內容
    getDates($("#movie").val())
    })
    }
  3. 取得某電影的上映日期函式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //取得選中的院線片可訂票日期
    function getDates(id){
    $.get("./api/get_dates.php",{id},(dates)=>{
    $("#date").html(dates);

    //分別取得目前選中的電影與日期
    let movie=$("#movie").val()
    let date=$("#date").val()

    //執行一次可訂場次的函式,參數中帶入電影id及所選的日期
    getSessions(movie,date)
    })
    }
  4. 取得某電影在某個上映期的各場次資料函式

    1
    2
    3
    4
    5
    6
    7
    //取得選中的院線片及指定日期的可訂票場次剩餘座位
    function getSessions(movie,date){
    $.get("./api/get_sessions.php",{movie,date},(sessions)=>{
    $("#session").html(sessions);
    })
    }

建立後端api程式

由於我們會使到多次關於場次的字串,因此可以先在 db.php 建立全域的共同變數
5. 在 db.php 中建立共用變數

1
2
3
4
5
6
$sess=[1=>'14:00~16:00',
2=>'16:00~18:00',
3=>'18:00~20:00',
4=>'20:00~22:00',
5=>'22:00~24:00',
];
  1. 回傳上映中電影資料
    ./api/get_movies.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    include_once 'db.php';

    // 取得今天的日期
    $today=date("Y-m-d");

    // 取得兩天前的日期
    $ondate=date("Y-m-d",strtotime("-2 days"));

    // 從資料庫中取得符合條件的電影資料
    $movies=$Movie->all(" where `ondate`>='$ondate' && `ondate` <='$today' && `sh`=1 order by rank");

    foreach($movies as $movie){

    // 回傳電影選項的html內容
    echo "<option value='{$movie['id']}'>{$movie['name']}</option>";
    }
  2. 回傳指定電影的上映日期資料
    ./api/get_dates.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    include_once 'db.php';
    // 取得電影id
    $movie=$_GET['id'];
    // 取得兩天前的日期
    $ondate=strtotime($Movie->find($movie)['ondate']);
    // 計算可訂票的日期
    $end=strtotime("+2 days",$ondate);
    // 取得今天的日期秒數
    $today=strtotime(date("Y-m-d"));

    // 取得可訂票的天數
    $diff=($end-$today)/(60*60*24);

    // 以迴圈來產生可訂票的日期選項
    for($i=0;$i<=$diff;$i++){
    // 產生日期字串
    $date=date("Y-m-d",strtotime("+$i days"));
    // 回傳日期選項的html內容
    echo "<option value='$date'>$date</option>";
    }
  3. 回傳指定電影及上映日期的場次資料
    ./api/get_sessions.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    include_once 'db.php';
    // 取得電影id
    $movie=$_GET['movie'];
    // 取得電影的名稱
    $movieName=$Movie->find($movie)['name'];
    // 取得訂購電影的日期
    $date=$_GET['date'];

    // 取得目前的24小時制的小時數
    $H=date("G");

    /**
    * 如果訂票觀看的日期不是今天,或是目前的時間在下午兩點前
    * 那麼應該會有五個場次可以選擇;
    * 如果要訂票觀看的日期是今天,而且時間已經超過下午兩點了
    * 那麼只能訂兩點以後還沒上映的場次
    * 我們在這裏計算出可以選擇的起始場次
    */
    $start=($H>=14 && $date==date("Y-m-d"))?7-ceil((24-$H)/2):1;

    for($i=$start;$i<=5;$i++){
    /***
    * 1. 去資料表撈出電影,日期,場次的訂單
    * 2. 根據訂單,計算座位數
    * 3. 在迴圈使用20-座位數來取得剩餘座位數
    */
    $qt=$Order->sum('qt',['movie'=>$movieName,'date'=>$date,'session'=>$sess[$i]]);
    $lave=20-$qt;
    echo "<option value='{$sess[$i]}'>{$sess[$i]} 剩餘座位 $lave</option>";
    }

建立聯動選單事件

  1. 接著要來分別註冊電影及日期選單被選擇時的行為(onchange),我們會在每個選單的選擇結束後,呼叫下一個選單的函式,並帶入需要的參數,以此達到選單連動的效果。
1
2
3
4
5
6
7
//註冊電影及日期選單的內容被選中時要連帶變動的下一個選單事件
$("#movie").on("change",function(){
getDate($(this).val())
})
$("#date").on("change",function(){
getSessions($("#movie option:selected").text(),$(this).val())
})