/10901-bquiz03

乙級第三題解題

Primary LanguagePHP

題組三解題步驟

步驟一:將素材目錄複製到崗位目錄下,確認素材內容與抽題題號一致

監評長按下倒數計時後,可以先把桌面上素材目錄中的題目素材複製一份到自己的工作目錄下,這時要確認自己複製的題目和抽到的題目是一致的,之後都在工作目錄下來取用相關的素材,這樣比較不容易出錯;在安裝軟體的準備時間裏,也要確認一下電腦桌面中是否有包含了素材這個目錄,並且四個題組的素材都在其中。


步驟二:將版型檔案及相關素材複製到網站根目錄下,並進行相應的更名及整理

  1. 開立./css, ./js, ./api, ./icon等常用目錄以利檔案分類及管理
  2. 將素材檔中的.css, .js, 及icon圖檔複製到相應的目錄下
  3. 更改版型素材的相關檔名,以符合解題的需要:
    • 03P01.htm => index.php
    • 03P02.htm => intro.php
    • 03P03.htm => admin.php
  4. 更改版型素材的相關連結及匯入檔內容
    • 修改 index.php<link><script> 中的連結路徑,指向正確的位置
    • 修改 ./css/css.css 中的圖片 url ,指向根目錄下的 ../icon 目錄,不過在此題組中,body設定中的 b.png 圖檔不存在,所以直接移除這個設定就可以了。
      body{
          background:url(../icon/b.png); /* 移除這行即可 */
          font-family:微軟正黑體;
      }
      
  5. 開立 ./img/ 目錄,把素材目錄中的預告片海報、院線片海報及影片檔都先複製過來
  6. 以上步驟是為了方便之後在製作列表和上傳檔案功能時,可以減少一些功夫,同時我們為了速度考量,並不會對上傳的檔案做更名之類的多餘動作,因此我們在做列表功能時,可以直接指定目錄及檔名來顯示相關的圖片或影片,而不用等到完成上傳檔案的功能後,才一個一個上傳
  7. 開啟 xamppapache 伺服器,使用 localhost127.0.0.1 檢視網頁是否正確顯示,css 的載入是否正確

步驟三:進行前後台的檔案整理及切版,分離出共用的區塊或功能

  1. 建立 frontbackend 兩個目錄,一個代表前台的相關檔案,一個代表後台的相關檔案,前後台共用的元件則先放在根目錄下,或另開一個 comm 目錄用來存放共用的元件。
  2. index.php 中找到中間主要內容區的區塊,切出去成為 main.php 放在 ./front/ 目錄中。
  3. intro.php 中找到中間主要內容區的區塊,排除首尾後成為 intro.php 移動到 ./front/ 目錄中。
  4. admin.php 中找到中間主要內容區的區塊,保留後台選單的部份,其它的內容切出去成為 main.php 放在 /backend/ 目錄中,不過因為這個 main.php 只有一行的內容,所以也可以用 echo 的方式寫死在 admin.php 中。
//另一個做法參考,省略home.php
  $do=(!empty($_GET['do']))?$_GET['do']:"";
  $path="./backend/".$do.".php";
  if(file_exists($path)){
    include $path;
  }else{
    echo "<h2 class='ct'>請選擇所需功能</h2>";
  }
  1. 使用 include 指令來重新組合 index.phpadmin.php 頁面,並加上判斷式來確保要組合的檔案是存在的。
  2. get 的方式來傳遞各頁面要組合的元件內容,比如 do=login 表示要看到的是登入頁面,因此在前台的 include 中可以併入 login.php 來呈現。
  3. 修改 index.phpadmin.php 中的連結內容及寫法,確保可以正確的連結到相應的頁面。
  4. 修改 admin.php 中的後台功能連結內容,後續的功能會用到。

步驟四:建立資料庫連線檔及常用函式。

  1. 建立 base.php 檔,用來放共用的設定及函式。
  2. 採用類別方式來包裝整個db的連線及資料表的存取函式
class DB{

//類別內容

}
  1. 設定好PDO的連線參數 $this->pdo=new PDO($setting,$user,$pw,$config)
    private $dsn="mysql:host=localhost;charset=utf8;dbname=db66";
    private $root="root";
    private $password="";
    private $pdo;

    //設定建構式
    public function __construct($table){

        //將建立物件時代入的資料表名稱代入類別中的屬性table
        $this->table=$table

        //建立pdo的連線資訊,並將pdo連線指定給類別內的屬性pdo
        $this->pdo=new PDO($this->dsn,$this->root,$this->password); 
    }
  1. 啟用session session_start()
  2. 建立全域變數或是共用函式
    • find($arg) - 尋找特定條件的單筆資料或第一筆資料
    • all(...$arg) - 取得資料表的全部資料或是特定條件的全部資料
    • count(...$arg) - 計算符合條件的資料筆數
    • save($arg) - 新增或更新單筆資料
    • del(...$arg) - 刪除特定條件的全部資料
    • q($sql) - 簡化 $pdo->query($sql)->fetchAll() 的使用;
    • to($url) - 簡化 header("location:xxxxxx") 的使用;
class DB{
    //......

    public function __construct($table){

        //.....

    }

  public function all(...$arg){
    //...... 
  }
  public function find($arg){
    //......
  }
  public function count(...$arg){
    //......
  }
  public function save($arg){
    //......
  }
  public function del($arg){
    //......
  }
  public function q($sql){
    //......
  }

}

function to($url){
    //......
}
  1. 做好以上工作後,可以先建一張簡單的資料表,把資料庫連線及所有自訂函式功能先測試一次,以確保後續使用不會有問題。

步驟五:建立資料表及預設資料。

每個題組依狀況不同,在這一步有不同的做法,視自己對題目的熟悉程度來做應變,可以一次把全部資料表建完,也可以視解題的進度來逐步建立或修改資料表。 根據題意,題組三會需要用到以下的資料表:

  • movie - 院線片資料表
  • ord - 訂單資料表
  • poster - 預告片資料表
  1. 依序建立功能需要的三張資料表:
  • movie

    name type pk default A_I note
    id int(10) yes yes 流 水 號
    name text 電影名稱
    level tinyint(1) 分級
    length int(5) 長度
    ondate date 放映日期
    publish text 發行商
    director text 導演
    trailer text 預告影片
    poster text 預告海報
    intro text 電影介紹
    rank int(5) 排序
    sh int(1) 1 顯示
  • ord

    name type pk default A_I note
    id int(10) yes yes 流水號
    no text 訂單編號
    movie text 電影名稱
    date date 觀影日期
    session text 場次
    qt int(1) 票數
    seat text 座位
  • poster

    name type pk default A_I note
    id int(10) yes yes 流水號
    path text 檔案路徑
    name text 片名
    rank int(5) 排序
    sh int(1) 1 顯示
    ani int(1) 1 轉場動畫
  1. 為了解題順利,可以把資料表中的一些欄位設為可接受空值的狀況,這樣即使未設定內容,也能正常新增或更改資料,不過這個做法只是為了先求解題完成而做的取巧,實務上應該根據需求及功能來決定欄位是否可以接受空值,並在程式端檢查來源資料是否為空值

步驟六:管理登入

題組三的管理登入算是簡單的功能,並不需要有個管理者的資料表來做紀錄,因此這邊只要直接寫死帳密做檢查即可;另外,雖然題目中沒有提到,但為了避免每次要到後台時都要再一次輸入帳號密碼,這邊建議還是建一個session變數來紀錄登入的狀態:

  1. admin.php 撰寫以session為判斷的登入程式,如果己經登入則可以選擇後台功能,如果未登入,則顯示登入表單。
  2. 因為會使用到session,所以記得要先在 admin.php 的最前面 include base.php 來啟用session的功能
  3. 撰寫登入判斷程式,帳號依題意寫死即可(帳號:admin,密碼:1234)
  4. 這邊要注意的是在未登入的狀況下,只顯示登入表單而己,後台的功能選單在未登入時是不顯示的。
  5. 由於素材提供的版型配色和字型等內容與題目的示意圖落差極大,因此題組三我們不太管示意圖的視覺配置了,只要功能符合就可以。
  6. 修改 admin.php 中的內容區域寬度,方便後續的程式撰寫
    <div class="rb tab" style="width:98%">
      <!---功能內容----->
    </div>
  1. 這邊要小心判斷式中包含的html區段,避免漏了tag沒包到造成版面出錯

步䮕七:後台預告片海報管理一

示意圖給的做法是把新增和管理都做在同一個畫面中,我們也採用一樣的畫面配置,但是美化先不考量;

另外,示意圖中並沒有給出轉場動畫的設定方式為何,因此要採用全區設定也可以,我這邊使用的做法是每個海報都可以單獨設定一個轉場動畫。

最後,示意圖中給出的排序方式是採用按鈕往上或往下來改變順序,但依照題意只要可以設定排序都可以,因此這邊的做法也可以採用直接填入數值的方式來達到排序的目的,我這邊使用的是ajax的方式以按鈕動作來改變排序。

  1. ./backend/ 中建立 poster.php
  2. 撰寫新增預告片海報的表單。
  3. ./api/ 目錄中建立 add_poster.php,並撰寫新增預告片寫入資料表的相關程式
  4. 撰寫預告片清單中的表單格式及區塊配置
  5. poster.php 中撰寫預告片海報列表的程式碼,由於會使用到排序的功能,因此要注意在取出資料時,要下 order by rank的指令,才會依照rank欄位值來排序(ASC 或 DESC都可以)。
  6. 建立 ./api/edit_poster.php 檔案並撰寫海報的編輯片名/顯示/刪除/動畫等功能
  7. 往上/往下的功能有兩種做法,一種是透過ajax來傳送要交換的資料id,讓後台去更新rank,一種是提供輸入框讓使用者自行輸入rank值,兩種做法都可以達成排序的目的。

步驟八:後台預告片海報管理二

這邊我們來處理排序的問題,題目要求要可以設定順序,但沒有說明設定的方式,因此有兩個方向可以製作,一個是提供一個調整順序的輸入框,直接輸入對應的順序,然後在步驟七中修改一下相應的頁面內容及api即可;這邊示範的是示意圖中的以按鈕的方式來調整順序的做法,我們利用ajax的方式來完成這個功能。

不管採用那個做法,後面在院線片管理中也會使用到改變順序的功能,因此只要做一次就可以複製給另一個功能來使用。

  1. ./backend/poster.php 中的按鈕標籤中增加資料的id值,這裏我們利用foreach迴圈的特性,同時計算出上一筆及下一筆的id值,然後帶入按鈕屬性中的id值。
    $prev=($k!=0)?$rows[$k-1]['id']:$row['id'];
    $next=($k!=(count($rows)-1))?$rows[$k+1]['id']:$row['id'];
  <!--如果要使用button 標籤,記得加上type=button的屬性,否則會預設為submit來使用-->
    <button type="button" data-rank="<?=$row['id']."-".$prev;?>">往上</button>
    <button type="button" data-rank="<?=$row['id']."-".$next;?>">往下</button>
  1. ./backend/poster.php 中撰寫按鈕事件來取得要交換的id值,並以ajax的方式來傳送到後台進行更新。
$("button").on("click",function(){
    let id=$(this).data("rank").split("-");
    $.post("api/rank.php",{id,"table":"poster"},function(){
        location.reload();
    })
})
  1. ./api/rank.php 中撰寫交換資料排序的php程式碼
include_once "../base.php";

$table=$_POST['table'];
$db=new DB($table);

$row1=$db->find($_POST['id'][0]);
$row2=$db->find($_POST['id'][1]);


$tmp=$row1;
$row1['rank']=$row2['rank'];
$row2['rank']=$tmp['rank'];

$db->save($row1);
$db->save($row2);
  1. 由於排序的交換功能在院線片中也會使用到,因此我們在設計api時增加了對資料表的判斷,做到可以相容各資料表
  2. 在ajax傳送完資料後,重新載入整個頁面這時會產生新的排序後的列表。

步驟九:後台院線片管理一

院線片管理的功能分成三個部份來處理:

  1. 首先是資料的手動增加及列表功能;
  2. 再來是處理院線片的刪除/顯示/排序功能;
  3. 最後是新增/編輯院線片的功能;

之所以會這樣安排是因為新增/編輯的表單欄位較多又有上傳檔案的功能,會花比較多時間來製作,加上分數只有十分,所以我個人都會先跳過這兩個小功能,先把佔分比較多且製作可以較快速的列表及按鈕功能做完再回頭來補,這樣的解題策略因人而異,同學們可以自行安排。

  1. ./backend/ 目錄中新增 movie.php 檔案,這是院線片管理的主要頁面。
  2. 由於題目沒有提供院線片的文字素材,因此我們可以先建立一個 tmp.php 自行寫一支小程式來快速建立需要的資料內容,執行完畢後資料表就會產生一堆院線片的資料,之後這個 tmp.php 檔可以刪除;除了寫程式的方式,也可以直接利用phpmyadmin來新增及複製數筆資料。
include "base.php";
//手動加入資料的方式之一,撰寫程式來插入資料
for($i=1;$i<=10;$i++){
    $data['level']=rand(1,4);
    $data['name']="院線片".$i;
    $data['length']=90;
    $data['ondate']=date("Y-m-d",strtotime("+".(($i-2)%5)." days"));
    $data['publish']="發行商".$i;
    $data['director']="導演".$i;
    $data['trailer']="03B".sprintf("%02d",$i)."v.mp4";
    $data['poster']="03B".sprintf("%02d",$i).".png";
    $data['intro']="院線片".$i."的劇情簡介"."院線片".$i."的劇情簡介"."院線片".$i."的劇情簡介"."院線片".$i."的劇情簡介"."院線片".$i."的劇情簡介"."院線片".$i."的劇情簡介";
    $data['rank']=$i;
    $data['sh']=1;
    save("movie",$data);
  }
  1. 透過2.的資料新增,我們不用先做新增院線片的功能也可以建置資料,因此接下來我們在 ./backend/movie.php 中撰寫院線片管理需要的頁面html碼
  2. ./api/ 目錄中新增 movie_list.php 檔案,用來以ajax載入列表之用。
  3. ./api/movie_list.php 撰寫電影列表的相關程式碼。
  4. base.php 中增加一個分級的陣列,這個陣列以我們在資料庫中設定的分級種類做為key值,而內容則以子陣列的方式存入分級圖檔的檔名及字串,加在 base.php 中的原因是要這個變數成為所有頁面都可以存取的變數
//建立一個分級資訊的陣列,儲存分級的icon檔名及分級的字串
$level=[
         1 => ["03C01.png","普遍級"],
         2 => ["03C02.png","輔導級"],
         3 => ["03C03.png","保護級"],
         4 => ["03C04.png","限制級"],
       ];
  1. 新增電影編輯電影 按鈕中增加js的跳頁功能及帶入需要的參數,讓頁面可以跳到對應的功能頁面去。
  2. 對於按鈕的大小和外形實在無法忍受的話,可以到 ./css/css.css 進行修改和調整,讓按鈕的外形看起來順眼一點,但這不做也不影響分數。
input[type='button'],input[type='submit'],input[type='reset'],button,.button
{
	min-width:40px; /*最小高度和寬度可以縮小一些*/
	min-height:20px;
	background:#000;
	color:#fff;
	border:none;
	cursor:pointer;
	font-size:14px; /*字型可以改小*/
	text-decoration:none;
	margin:3px 6px; /*增加上下左右的邊距*/
	border-radius:5px; /*增加點圓角*/
}

步驟十:後台院線片管理二

完成列表功能後,接下來製作各個按鈕的功能,示意圖中不像預告片那邊有一個確認編輯的按鈕,因此我們可以理解為每部院線片的設定都是獨立的,但是題目本身並沒有指定到底要怎麼做,因此延用預告片的做法也是可以的,我在這邊使用的是接近示意圖的做法,也就是儘可能使用ajax來完成所有按鈕功能的操作,每一次的操作也只針對一筆資料來處理。

  1. 顯示按鈕的功能,需要告知api是那張表格的那筆資料要改為隱藏,因此我們在 ./api/movie_list.php 的顯示按鈕中註冊onclick事件並執行函式sh(movie,id)
  2. ./backend/movie.php 中撰寫javascript程式嗎,處理顯示按鈕的功能
  3. 建立 ./api/sh.php 並撰寫更改顯示值的語法
  4. 往上往下按鈕的功能,複製 ./backend/poster.php 中的排序按鈕js,並修改相應的資料表名,即可完成排序的功能,要記得在 ./api/movie_list.php 中增加排序的sql語法,api還是使用 ./api/rank.php ,只要記得帶上table名就可以了
  5. 刪除按鈕的功能,在 ./api/movie_list.php 的刪除按鈕中註冊onclick事件,並執行del(table,id)
  6. ./backend/movie.php 中增加刪除功能的事件註冊及相應的行為
  7. 新增 ./api/del.php ,並撰寫刪除功能的程式碼

步驟十一:後台院線片管理三-新增/編輯院線片

示意圖給出的表單範例做起來有點囉嗦,所以這邊建議先把功能完成,回頭有空再來處理視覺的問題,而且因為這兩個功能加起來只有10分,如果不能在15分鐘內完成的話,實在不值得花太多時間在這裹,我這邊使用的做法先不管美觀和排版,先以縮短這兩個小項目的製作時間為主,如果沒有把握可以把兩個項目快速做完,會建議先去處理其它的功能再回頭來補完這兩個項目。

  1. ./backend/ 目錄下新增 add_movie.php 檔案,並撰寫需要的表單內容,示意圖中左側的"影片資料"及"劇情簡介"兩個字串並不是必須的,排列方式以簡單快速為主。
  2. ./api/ 目錄下新增 edit_movie.php 檔案,並撰寫需要的PHP程式碼,這邊我們增加對id的判斷來讓這個程式可以同時處理新增及編輯功能。
  3. 依題意最麻煩的是上映日期規定要使用三個下拉選單,但資料表中只有一個ondate欄位,因此要在api中將這三個欄位組合成日期格式後才能存入資料表。
  4. 由於表單提供使用者可以上傳海報及影片,所以要記得做兩個判斷式來處理檔案上傳的動作
  5. 另外要記得處理排序欄位及顯示欄位,排序欄位的值我們以sql語法直接向資料尋找id的最大值再加1來當成rank欄位的值
  6. 複製 ./backend/add_movie.php 成為 ./backend/edit_movie.php ,並加入取得資料及在各欄位寫入欄位值。

步驟十二:前台院線片清單製作

題組三的三個前台功能中,院線片清單算是簡單的,主要就是照題意來列出四部院線片再加上分頁功能就可以了;

但是由於素材提供的css樣式和題目的不一樣,所以在這很容易就造成版面過擠不好看,但美觀的事可以晚點再做,我們先把功能完成,再回頭修一下 CSS 即可。

  1. 先在 index.php 的最上頭引入 base.php
  2. 可以在前台顯示的院線片有以下條件:
    • 在後台管理中被設為 顯示 的影片
    • 上映日起算的三天日期在觀影日內
  3. 刪除原本的 table 標籤區段,由於版型css已經不一樣了,使用表格來做排版反而麻煩,因此這邊我們建立一個新的容器,並使用flex及自己定義的css來做版面的簡單設定
  4. 由於我們在 base.php 中並沒有對 && 以外的條件做設計,因此這邊無法使用 all() 函式來取出所有符合條件的資料,我們使用 q() 函式來直接寫入SQL語法並取得符合條件的所有資料
  5. 建立分頁需要的各項變數,並將 limit 語法寫入SQL語法中
//取得符合條件的資料語法
    $today=date("Y-m-d"); //今天的日期字串
    $startDay=date("Y-m-d",strtotime("-2 days"));  //距離今天兩天前的日期字串
    ...
      分頁需要的各項變數
    ...

    //取得今天可觀看的影片資料
    $movies=q("select * 
                 from movie 
                where sh=1 && 
                      ondate >='$startDay' && 
                      ondate <='$toDay' 
                order by rank
                limit $start,$div ";
              );
    
  //另一種取得日期區間的SQL語法  
    $movies=q("select * 
                 from movie 
                where sh=1 && 
                      ondate between '$startDay' AND '$today'
                order by rank
                limit $start,$div ";"
              );
  1. 利用迴圈將題意所需的圖片,資訊及連結分頁輸出至頁面上
  2. 撰寫基本的css來控制畫面的呈現,不用寫得太複雜太漂亮,能看就好,主要調整的是圖片的大小,位置排列的關係,字形大小,我會使用flex來做控制
  3. 最後處理劇情簡介頁面,也就是在 ./front/intro.php 中撰寫讀出資料的相關語法,並把資料放在對應的位置中,原始提供的版型有可能會造成奇怪的斷行或位置不太正確的狀況,這些問題可以晚點再處理,這邊只要先確認功能是正常的,影片可以播放就好了。

步驟十三:前台預告片展示製作

預告片動畫算是有難度的一個製作項目,這邊採用做法是依照示意給出的範例來製作,實際檢定時,可以視時間減少一些功能或檢查的工作,讓解題速度可以快一些,在撰寫javascript的動畫相關功能時,一定要特別注意js的非同步問題,避免奇怪的問題發生。

  1. 原版型中所附的s2.css內容並不實用,加上我們不清楚原本的js怎麼寫的,因此我們這裹自己寫全新的css內容供js控制之用,有些美觀用的css設定可以再做簡化或忽略,爭取解題時間。
  2. 這邊我們利用了不少css的flexbox model原理來設定物件的位置和排列,相關的css應用方式,請同學們要多多練習和熟悉
  3. 動畫的部份我們只使用了jquery內建的fadeIn(),slideDown(),show()等簡單的動畫方式,較複雜的動畫可以參考animate()函式的使用說明
  4. 這邊的js中有多加了幾段額外的程式,用來做按鈕的控制或是避免錯誤,但檢定時,可視作答時間來決定要不要多寫這些內容,因為檢定時是由應檢人展示給監評看,所以只要操作上小心點,有些額外的程式是可以先略過的。

步驟十四:前台線上訂票功能-電影及場次選擇

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

  1. ./front/ 目錄下建立 order.php 檔案,並撰寫基本的頁面html碼,這邊我們會建立三個下拉選單的項目,但是選項內容可以先空著,選單中的下拉選項會全部由ajax的方式從後端來取得,這邊的CSS美化都可以晚點再做,先把畫面該有的元素及功能完成即可
  2. order.php 中建立javascript程式碼,用來做選單的連動及訊息的回傳,這邊我們會完全使用ajax來完成。
  3. 建立 getMovie() , getDuration() , getSession() 三支js函式來分別取得電影列表,播放日期,可訂票場次的選項
  4. 其中 getMovie() 還要負責網址的解析,取得參數id來判斷使用者是由院線片的訂票來的還是直接從選單中的 線上訂票 連結來的,這邊我們使用到 WEB API中的 URL 這個API來協助我們解析網址參數,省去使用字串分析的時間,另一個後端的做法是使用PHP語法先將參數取得,再寫入script區段。
    //利用URL API建立一個網址物件,並將目前的網址傳入
    let url=new URL(location.href)

    //取得網址物件中的參數id的值
    let param=url.searchParams.get("id")

    //先建立一個id變數,值為0
    let id=0;

    //利用jQuery的isEmptyObject()函式來判斷網址中是否有id這個參數,
    //如果網址中有帶id這個參數,則將值指定給id這個變數,否則id維持0
    if(!$.isEmptyObject(param)){
      id=param
    }
   //判斷是否有帶電影的id,有的話則需選中該電影,沒有的話則照資料表撈出的順序來顯示電影列表
   if(!empty($_GET['id'])){
       $selected=($_GET['id']==$row['id'])?"selected":"";
       echo "<option value='".$row['id']."' data-name=".$row['name']." $selected>".$row['name']."</option>";
   }else{
       echo "<option value='".$row['id']."'  data-name=".$row['name'].">".$row['name']."</option>";
   }
  1. 在訂單頁面被載入時,要先執行一次 getMovie() 函式來建立電影選單,此時如果網址沒有帶 id 參數,則是依照資料庫取出的電影順序列出,如果網址中有帶 id 參數,則選單會將指定的電影設為選中的狀態,最後要記在電影選單以ajax的方式載入後,重建一下 變數id 的值,如果原本 變數id 是0,則在電影選單載入後,應取得第一筆 電影的id值 做為 變數id 的值,如果id已經被指定值,則不用做任何更改,因為我們接下來會把這個值帶去給下一個取得日期的函式使用,達到連動選單的效果。
  2. ./api/目錄中分別建立 get_movie.php,get_duration.php,get_session.php 三支API,這三支API會根據前端傳遞過來的參數進行資料的取得及處理,然後分別回傳 電影列表 , 可訂票日期 , 可選場次 選單給前端使用。
  3. 由於題目的要求,在撰寫這三支API時,一定要搞懂題目的意思,在資料的取得上,條件會比較複雜一些,因此SQL語法也會比較複雜許多。
  4. 接著要來分別註冊電影及日期選單被選擇時的行為,我們會在每個選單的選擇結束後,呼叫下一個選單的函式,並帶入需要的參數,以此達到選單連動的效果,最後也要在資料被載入網頁後註冊 確定 按鈕被點選的行為,這邊我們不使用表單的submit而是另外寫ajax的函式。
$("#movie").on("change",function(){
    //取得選項的值,然後傳給getDate()
})

$("#date").on("change",function(){
    //取得選項的值,然後傳給getSession()
})

function booking(){
  //選完電影,日期,場次,準備載入劃位畫面

}
  1. 為了方便可以隨時取得表單的值,我們開以另外寫一個函式來取得表單的內容,這個函式使用到了javascript的物件特性,讓我們可以用較簡便的方式來取得各個下拉選單,甚至整個表單的內容
function getForm(){
  let id=$("#movie").val()
  let date=$("#date").val()
  let session=$("#session").val()
  return {"id":id,"date":date,"session":session}
}
  1. 由於訂票和後台有很多機會使用到場次的字串,因此我們在 base.php 中建立一個場次的字串陣列,方便取用。
//建立一個場次的文字陣列,儲存場次的字串,方便取用
$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. 由於題組三會使用到時間的計算,而php預計的時區和台北這邊差了八小時,除了可以在php.ini中設定系統時區外,也可以直接在程式中下指令來設定程式執行期間的時區;
//設定時區
date_default_timezone_set("Asia/Taipei");

步驟十五:前台線上訂票功能-劃位功能及訂票完成

這邊題目給出的指示需要摸擬一個影廳的座位狀況,然後使用者可以點選座位來訂票,所以會需要一些建置前端頁面的工作;

這邊會先使用php來取出已訂位的資料,建置完座位區後,再以js來完成前端劃位的操作,最後再把資料送到後端去完成整個訂票的紀錄。

由於題目有要求做出上一步回選單並保留選項的功能,因此我們採用ajax的方式來載入劃位的資料,而選單則使用控制顯示及隱藏來達到保留狀態的目的。

  1. ./front/order.php 中加入一個 div ,我們會使用ajax來載入劃位畫面。
  2. ./api/ 目錄中建立 get_seats.php 檔,這個檔案會根據傳送過來的 電影id日期場次 資料來生成劃位的畫面
  3. 在使用者按下訂票選單中的確定按鈕後,我們使用ajax的方式傳送訂票的資料到 ./api/get_seats.php ,然後載入符合訂票資料所需的場次劃位畫面,
  4. ./api/get_seats.php 中撰寫生成畫面元素的程式碼,這邊我們主要是利用css來達到排出座位表的功能,也可以考慮使用表格的方式來呈現。
  5. 撰寫判斷座位是否已訂位的程式,這邊我們要先從資料表中去撈出該場次己經被訂走的座位,然後在產生座位表時,逐一檢查每個座位是否開放訂票。
    $db=new DB("ord");
    //取得ajax傳來的資料
    $movie=$_GET['movieName'];
    $date=$_GET['date'];
    $session=$_GET['sessionName'];

    //取得符合條件的訂單資料
    $ords=$db->all([
        "movie"=>$movie,
        "date"=>$date,
        "session"=>$session
    ]);

    $seat=[];

    //將訂單的座位資料合併成一個陣列
    foreach($ords as $ord){
        $seat=array_merge($seat,unserialize($ord['seat']));
    }

    //用判斷式來決定座位是否被訂走,並顯示對應的class
    if(in_array($i,$seat)){
        echo "<div class='booked'>";
    }else{
        echo "<div class='null'>";
        echo "<input type='checkbox' name='num[]' value='".$i."class='chkbox'>";
    }
  1. 撰寫js來進行劃位操作的檢查,這邊要注意使用者的操作行為可以劃位也可以取消,因此兩種狀況都要考慮進去。
  2. 撰寫上一步的按鈕功能,這邊我們採用顯示/隱藏的方式來處理表單,即可做到保留選取狀態的功能,而清空劃區塊的內容則可以做到清除劃位的各項變數及劃位的狀況。
  3. 撰寫送出訂單儲存的功能,會先用 $.post()的方式將訂單資料傳送給 api/order.php處理,然後回傳拿到訂單編號,再使用location.href的方式將畫面導向訂購結果頁。
  4. ./front/ 目錄中建立 result.php 檔案。
  5. result.php 中撰寫訂票結果頁,這邊會在網址中傳入訂單編號,據此可以取得訂單結果。
  6. 電影票訂單的示意圖中有一顆 確認 的按鈕,但題目中沒有說明這個按鈕按了之後要去那裏,我是讓這顆按鈕按了之後會回到首頁,但不做任何功能應該也是沒關係的。

步驟十六:後台電影票訂單管理

訂單管理功能也算是相對簡單的功能,如果不想等做完訂票功能才來做後台訂單管理的話,可以參考院線的做法,先利用程式的方式來產生數筆訂單資料,這樣就可以先來完成訂單管理功能了。

  1. ./backend/ 目錄中新增 order.php 檔案,並撰寫訂單管理功能需要的基本版面內容
  2. ./backend/ 目錄中新增 orderlist.php 檔案,並撰寫訂單列表的功能
  3. ./backend/order.php 中撰寫js函式 getList() 用來做為ajax載入列表的函式,也可以直接從 poster.phpmovie.php 複製過來修改
  4. ./backend/order.php 中的 getList() 建立刪除按鈕的點擊事件,並利用先前寫過的 ./api/del.php 來完成刪除單筆訂單的功能,刪除單筆訂單的功能並沒有提到需要做確認的動作,因此是否要做確認可自行決定。
  5. ./backend/order.php 中建立 qDel() 函式,並撰寫相關的取值及確認動作
  6. ./api/ 目錄中建立 qDel.php 檔案,依照前端傳過來的條件刪除資料

最後的檢查

題組三的難點在於前台的預告片轉場動畫及訂票劃位功能上,所以如果做完有空,可以先檢查一下這兩個功能,確認分數有拿到;相較於一,二題以四小時內可以做完為目標,三,四題的目標放在四小時內可以做到及格就好了,因此可以在戰略上分配好,那些功能是可以押後來做,把時間留給有把握的功能上,並加強檢查。