:::
13-4 報名過後,就不可再報
- 其實,我們已經悄悄的內建此功能了!為什麼?因為我們當初設計資料表時,就把「uid」和「action_id」組合成主索引,主索引只能有一組,所以絕對不會讓您有機會出現第二筆重複資料。若硬是要報名就會出現「Duplicate entry '2-1' for key 'PRIMARY'」的訊息。
- 「那為何還要提出來修改?」因為,您覺得使用者看得懂「Duplicate entry '2-1' for key 'PRIMARY'」是啥意思嗎?更別說當使用者明明報完活動了,卻還在該活動頁面看到「我要報名」的按鈕,這時心裡會如何評價這位開發者呢?
- 所以,請修改一下列處,以及活動頁面裡面,偵測,若使用者已經報名,就不顯示「我要報名」的按鈕。
- 思考一下,作法有那些?
一、建議作法
- 登入時就撈出所有已經參加的資料,存成陣列,並放入session
- 列出活動時,只要利用in_array()判斷該活動有無在陣列中即可。
- 優點,只多做了一次SQL請求就可以搞定。
二、修改 login() 登入函數
- 修改 index.php 中的 login 函數,在登入成功後撈取該使用者所有已報名的活動編號
//登入 function login() { global $db; $email = clean_var('email', 'Eamil', FILTER_VALIDATE_EMAIL); $pass = clean_var('pass', '密碼'); $sql = "SELECT * FROM `users` where `email`='{$email}'"; $result = $db->query($sql); if (!$result) { throw new Exception($db->error); } $data = $result->fetch_assoc(); if (password_verify($pass, $data['pass'])) { $_SESSION['group'] = $data['group']; $_SESSION['name'] = htmlspecialchars($data['name'], ENT_QUOTES); $_SESSION['uid'] = $data['uid']; $_SESSION['email'] = htmlspecialchars($data['email'], ENT_QUOTES); //抓取該使用者已報名的活動編號 $sql = "SELECT action_id FROM `signups` where `uid`='{$data['uid']}'"; if (!$result2 = $db->query($sql)) { throw new Exception($db->error); } $_SESSION['uid_signup'] = []; while (list($action_id) = $result2->fetch_row()) { $_SESSION['uid_signup'][] = $action_id; } } else { throw new Exception("登入失敗!"); } } -
我們將活動編號都放入 $_SESSION['uid_signup'] 陣列中
-
另外,讀取資料庫的迴圈中若還有讀取資料庫迴圈,其 $result 記得改名,否則第一個迴圈的 $result 會被 第二個迴圈的 $result 給取代。
-
由於第二個迴圈只抓了一個欄位,故改用 $result2->fetch_row() 來抓,並利用 list() 做指派,把值放到 $action_id 中。
三、修改 logout() 登出函數
- 既然登入多了一組 session,登出時也應該要拿掉才是。
//登出 function logout() { unset($_SESSION['group']); unset($_SESSION['name']); unset($_SESSION['uid']); unset($_SESSION['email']); unset($_SESSION['uid_signup']); }
四、修改 signup() 報名函數
- ,這部份很容易就被忽略,這是指登入後,如果又去報名其他活動,那麼報名的當下,應該要把該活動也加到 $_SESSION['uid_signup'] 陣列中才合理。
//報名 function signup($action_id) { global $db; $uid = $_SESSION['uid']; $sql = "INSERT INTO `signups` ( `action_id`, `uid`, `signup_date`) VALUES ('{$action_id}', '{$uid}', NOW())"; if (!$db->query($sql)) { throw new Exception($db->error); } $_SESSION['uid_signup'][] = $action_id; }
五、修改主樣板的活動列表
- 我們直接在樣板中判斷即可,編輯 list_action.tpl
{if $group=="admin"} <a href="javascript:delete_action({$action.action_id})" class="btn btn-danger btn-xs">刪除</a> <a href="admin.php?action_id={$action.action_id}" class="btn btn-warning btn-xs">修改</a> {elseif $group=="user"} {if $action.action_id|in_array:$smarty.session.uid_signup} <a href="index.php?action_id={$action.action_id}" class="btn btn-danger btn-xs">取消報名</a> {else} <a href="index.php?op=signup&action_id={$action.action_id}" class="btn btn-primary btn-xs">我要報名</a> {/if} {/if} -
我們利用smarty的變數修飾器,直接使用 php 的 in_array() 函數來判斷目前此活動編號有無在 $_SESSION['uid_signup'] 陣列中
六、修改單一活動頁面下方報名按鈕
- 一樣直接在樣板中判斷即可,編輯 show_action.tpl
<div class="text-center"> {if $group=="admin"} <a href="javascript:delete_action({$action.action_id})" class="btn btn-danger ">刪除</a> <a href="admin.php?action_id={$action.action_id}" class="btn btn-warning">修改</a> {elseif $group=="user"} {if $action.action_id|in_array:$smarty.session.uid_signup} <a href="index.php?action_id={$action.action_id}" class="btn btn-danger btn-lg">取消報名</a> {else} <a href="index.php?op=signup&action_id={$action.action_id}" class="btn btn-primary btn-lg">我要報名</a> {/if} {/if} </div>
13-3 同時讀取兩個資料表