# 【上課】Jquery,Medoo,PHP > 已完成的內容:[連結點我](https://meng.finf.idv.tw/teach/class110/) ## 建立上課首頁 ### 建立bootstrap5與navbar 在官網上看到的navbar樣式 ![image](https://hackmd.io/_uploads/BJTEZ5mMA.png) 比較常看到的navbar樣式,按鈕們會靠右手邊,如圖所示: ![image](https://hackmd.io/_uploads/HJM3-9XMA.png) 基本上就是加上 <b>justify-content-end</b>就好 `<div class="collapse navbar-collapse justify-content-end" id="navbarNav">` 可參考下方的程式: ```html= <!DOCTYPE html> <html lang="zh-tw"> <head> <title>class110上課練習</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="./assets/css/global.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light p-2 shadow"> <div class="container-fluid"> <a class="navbar-brand" href="./"><b>Learn</b></a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse justify-content-end" id="navbarNav"> <ul class="navbar-nav"> <!--教學文件可以不需要增加--> <li class="nav-item"> <a class="nav-link" href="#">教學文件</a> </li> </ul> </div> </div> </nav> </body> </html> ``` ### 加入google fonts [google fonts 連結](https://fonts.google.com/noto/specimen/Noto+Sans+TC) 1. 在google fonts找Noto Sans Traditional Chinese(如下圖),並點選get font ![image](https://hackmd.io/_uploads/HyQ_K5mfC.png) 2. 選擇Get embed code ![image](https://hackmd.io/_uploads/BySTtqmM0.png) 3. 加入樣式 - html header ```html= <head> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100..900&display=swap" rel="stylesheet"> </head> ``` - CSS ```css= /*custom css*/ body{ font-family: "Noto Sans TC", sans-serif; font-optical-sizing: auto; font-style: normal; } ``` 目前font-weight呈現,結果如下圖: ![image](https://hackmd.io/_uploads/Byw166aGR.png) 4. 加入文字的font-weight 當需要不同文字樣式的時候,只要加入對應的class即可。 ```css= .font-w200{ font-weight: 200; } .font-w300{ font-weight: 300; } .font-w400{ font-weight: 400; } .font-w500{ font-weight: 500; } ``` ### 其他樣式 #### banner ```html= <div class="container-fluid p-5 mb-5 bg-light text-dark text-center font-w300"> <h1 class="mt-3">準備好進入學習的世界了嗎</h1> <p class="mb-3">再下方選擇你要進入的頁面</p> </div> ``` #### 按鈕選項 在header上要加入 bootstra-icons [官網連結](https://icons.getbootstrap.com/) ` <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">` ```html= <div class="container text-center mt-5"> <div class="row"> <div class="col"> <button class="btn stats-button blue"> <i class="bi bi-code-slash"></i> <div class="pt-2" style="font-size: 1rem;"><b>First</b></div> <div>JS練習</div> </button> </div> <div class="col"> <button class="btn stats-button red"> <i class="bi bi-journal-plus"></i> <div class="pt-2" style="font-size: 1rem;"><b>Second</b></div> <div>新增練習</div> </button> </div> <div class="col"> <button class="btn stats-button blue"> <i class="bi bi-person-plus"></i> <div class="pt-2" style="font-size: 1rem;"><b>Third</b></div> <div>註冊練習</div> </button> </div> <div class="col"> <button class="btn stats-button red"> <i class="bi bi bi-door-open"></i> <div class="pt-2" style="font-size: 1rem;"><b>Fourth</b></div> <div>登入練習</div> </button> </div> </div> </div> ``` ```css= /*index button css*/ .stats-button { width: 200px; height: 200px; border: none; color: white; font-size: 20px; margin: 10px; padding: 20px; box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15); } .blue { background-color: #395e85; } .red { background-color: rgba(158, 83, 83)} .blue:hover { background-color: #395e857c; } .red:hover { background-color: rgba(158, 83, 83, 0.53)} .stats-button i { font-size: 30px; margin-bottom: 10px; } ``` ## JS練習 ### 版面樣式 #### banner樣式 ```html= <div class="container-fluid mt-3 mb-5 text-dark font-w300"> <h2>&ensp;<b>-</b>&ensp;JS練習</h2> </div> ``` #### bs5 card [官網連結](https://www.w3schools.com/bootstrap5/bootstrap_cards.php) ```html= <div class="container"> <div class="row"> <div class="col-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">1.程式執行</h4> <p class="card-text">若無法理解可以把console.log,改為alert去查看</p> </div> </div> </div> <div class="col-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">2.區域和全域變數</h4> <p class="card-text">若無法理解可以把console.log,改為alert去查看</p> </div> </div> </div> </div> </div> ``` ### 程式執行順序 1. 程式起始點 若不知道程式,從哪裡開始跑,可以先找起始點,下方這兩段是相等的。 ```JS= $(document).ready(function(){ }); `````` <b style="color:red">相等</b> ```JS= $(function(){ }); ``` 2. 加入一些function查看 ```JS= function runA(){ console.log('已經跑到A段'); } function runB(){ console.log('已經跑到B段'); } function runC(){ console.log('已經跑到C段'); } $(function(){ console.log('開始執行'); runA(); runB(); runC(); }); ``` 3. 練習 - 我希望加上function run D(),執行順序為runA -> runB -> runD -> runC。<b style='color:blue'>但我的runD並不能放在我一開始程式起始點</b> ### 全域&區域變數 1. <b>全域變數:</b>在scirpt最上方加上變數,並查看執行順序 ```JS= <script> var t1='t1'; function runA(){ console.log('已經跑到A段'); console.log(t1); } function runB(){ console.log('已經跑到B段'); } function runC(){ console.log('已經跑到C段'); console.log(t1); } $(function(){ console.log('開始執行'); runA(); runB(); runC(); }); </script> ``` 2. <b>區域變數:</b>在runB內加上變數,並查看執行順序 ```JS= <script> var t1='t1'; function runA(){ console.log('已經跑到A段'); console.log(t1); } function runB(){ var t2='t2'; console.log('已經跑到B段'); } function runC(){ console.log('已經跑到C段'); console.log(t1); console.log(t2); } $(function(){ console.log('開始執行'); runA(); runB(); runC(); }); </script> ``` 3. 練習-我要怎麼樣才可以把runB的區域變數,傳到runD裡面? ### Jquery button click 1.樣式上先加上兩個button ```JS= <div class="container mt-4"> <div class="row"> <div class="col-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">3.Jquery - click</h4> <button class="btn btn-dark">方法1</button> <button class="btn btn-outline-dark">方法2</button> </div> </div> </div> </div> </div> ``` 2.<b>方法1</b>直接加上onclick="<functionName>",就可以直接執行function內容。 ```JS= <script> function button1(){ alert("hi~我是button1"); } </script> <button class="btn btn-dark" onclick="button1()">方法1</button> ``` 3. <b>方法2</b>需要加上id,並且在程式執行點上進行呼叫,才可以執行。 ```J <script> function button2(){ alert("hi~我是button2"); } $(function(){ $("#btn2").click(function(){ button2(); }); }); </script> <button class="btn btn-outline-dark" id="btn2">方法2</button> ``` 4. 練習1-請用方法1的方式,hwBtn1()做加法運算。 練習2-請用方法2的方式,hwBtn2()做減法運算。 可用alert的方式呈現計算結果。 提示如下: ```JS= function hwBtn1(){ var A=50; var B=2 } function hwBtn2(){ var A=100; var B=20; } ``` ### Jquery change 1. 加上input樣式 ```JS= <div class="col-md-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">4.Jquery - change</h4> <input class="form-control mb-2" type="text" id="inputTxt" /> <b>內容:</b><span class="font-w300 text-danger" id="showTxt"></span> </div> </div> </div> ``` 2. change的Jquery ```JS= <script> $("#inputTxt").change(function(){ var inputTxt=$("#inputTxt").val(); $("#showTxt").html(inputTxt); }); </script> ``` ### sessionStorage v.s. localStorage - sessionStorage 在每次分頁或瀏覽器關掉後就會清除 - localStorage 需要手動清除 #### html 內容 ```html= <div class="container mt-4"> <div class="row"> <div class="col-md-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">5.sessionStorage</h4> <input class="form-control mb-2" type="text" id="sessionTxt" /> <p id="sessionShow"></p> <button class="btn btn-primary" onclick="clearSession()">清除</button> <button class="btn btn-info" onclick="clearAllSession()">全部清除</button> </div> </div> </div> <div class="col-md-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">6.localStorage</h4> <input class="form-control mb-2" type="text" id="localTxt" /> <p id="localShow"></p> <button class="btn btn-primary" onclick="clearLocal()">清除</button> </div> </div> </div> </div> </div> ``` #### 紀錄storage內容 ```JS= <script> $("#sessionTxt").change(function(){ var sessionTxt=$("#sessionTxt").val(); sessionStorage.setItem('session', sessionTxt); }); $("#localTxt").change(function(){ var localTxt=$("#localTxt").val(); localStorage.setItem('local', localTxt); }); </script> ``` #### 取得storage內容 ```JS= <script> $("#sessionTxt").change(function(){ var sessionTxt=$("#sessionTxt").val(); sessionStorage.setItem('session', sessionTxt); }); $("#localTxt").change(function(){ var localTxt=$("#localTxt").val(); localStorage.setItem('local', localTxt); }); </script> ``` #### 清除storage內容 ```JS= function clearSession(){ sessionStorage.removeItem("session"); $("#sessionTxt").val(""); } function clearAllSession(){ sessionStorage.clear(); } function clearLocal(){ localStorage.removeItem("local"); $("#localTxt").val(""); } </script> ``` <b>練習</b>: 複製下方的內容至網頁上,按下儲存按鈕後,session的內容會在‵id="showHW"呈現。 需要再多一個清除的button,幫我把功課所記錄的session做清除。 ```HTML= <div class="container mt-4 mb-5"> <div class="row"> <div class="col-md-6"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title">7.sessionStorage HW</h4> <input class="form-control mb-2" type="text" id="txtHw" /> <button class="btn btn-outline-primary">儲存</button> <p>內容<span id="showHw"></span></p> </div> </div> </div> </div> </div> ``` > 題外練習:HTML DOM Element insertAdjacentHTML() insertAdjacentHtml() 有幾個不同的模式。 | value | description | | |--------------|------------------------------------------------------|---------------------------------------| | afterbegin | After the beginning of the element (first child) | 在元素的開頭之後(第一個子元素之前) | | afterend | After the element | 在元素之後 | | beforebegin | Before the element | 在元素之前 | | beforeend | Before the end of the element (last child) | 在元素的結尾之前(最後一個子元素之後) | 1.以Card為主體,並加上對應的mode,呈現的上下內容是不同的,用JS寫上的insertAdjacentHTML(黃色的)。 2. 若直接在editor寫上HTML(紫藍色),黃色對應紫色呈現狀態,如下圖所示。 圖片如下: ![image](https://hackmd.io/_uploads/rJ3rFzvmC.png) [參考網址](https://meng.finf.idv.tw/teach/class110/praAdjacent.html) * 建立/assets/js/navbar.js,程式如下: ```JS= document.addEventListener("DOMContentLoaded", function () { const navbar = ` <nav class="navbar navbar-expand-lg navbar-light bg-light p-2 shadow-lg font-w400"> <div class="container-fluid"> <a class="navbar-brand" href="./"><b>Learn</b></a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse justify-content-end" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" target="_blank" href="https://hackmd.io/@DV4sdErwTzmcRsdJP9ojiw/HkI5iFmzR">教學文件</a> </li> <li class="nav-item"> <a class="nav-link" target="_blank" href="./openssl.php">PHP加密</a> </li> </ul> </div> </div> </nav>`; document.body.insertAdjacentHTML('afterbegin', navbar); }); ``` * 把原本的程式註解掉,並加上script即可。 ## 註冊練習 ### 資料庫 1. 資料庫型態,可參考該內容 [連結](https://chwang12341.medium.com/mysql-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-%E5%9B%9B-mysql%E4%B8%AD%E7%9A%84%E8%B3%87%E6%96%99%E9%A1%9E%E5%9E%8B-data-type-%E5%A6%82%E4%BD%95%E5%89%B5%E5%BB%BAtables%E8%B3%87%E6%96%99%E8%A1%A8-%E5%A6%82%E4%BD%95%E6%93%8D%E4%BD%9C%E8%B3%87%E6%96%99%E8%A1%A8-%E5%BF%AB%E9%80%9F%E7%82%BA%E8%87%AA%E5%B7%B1%E5%89%B5%E5%BB%BA%E4%B8%80%E5%80%8B%E8%B3%87%E6%96%99%E8%A1%A8-927e0c365d6e) 2. 建立資料庫在dbadmin,使用Mysql,關於註冊會建立為下方的架構 ![image](https://hackmd.io/_uploads/rJJtyVCf0.png) 3.查看count sql語法 ```sql= SELECT count(id) as CNT FROM `student_member` WHERE `userMail` = 'test01@gmail.com' ``` 對應呈現內容如下: ![image](https://hackmd.io/_uploads/HJ6C4H0fC.png) > 關於文字上的條件搜尋: > <b style='color:red'>=</b> 欄位內容需要一模一樣 > <b style='color:red'>LIKE</b> 只要有符合文字內容即可 > > 關於數字上的條件搜尋: > <b style='color:red'><</b> 欄位內容大於搜尋內容 > <b style='color:red'><=</b> 欄位內容大於等於搜尋內容 > <b style='color:red'>></b> 欄位內容小於搜尋內容 > <b style='color:red'>>=</b> 欄位內容小於等於搜尋內容 文字+數字: > <b style='color:red'>!=</b> 欄位內容不等於搜尋內容 4. 新增sql語法 <b>(!)新增的內容,每一個欄位都需要填寫,若沒有填寫內容可寫"NULL"</b> ```sql= INSERT INTO `student_member` (`id`, `userName`, `userMail`, `userPwd`, `createTime`) VALUES (NULL, 'test01', 'test01@gmail.com', 'password0001', '2024-05-12 20:01:15'); ``` 對應呈現內容如下: ![image](https://hackmd.io/_uploads/HkSbWV0GA.png) ### 註冊畫面 在註冊畫面上,我並不會使用bs5,會直接利用CSS去做RWD。 * 建立CSS檔案 ./assets/custom-regLogin.css 背景色gradient [顏色參考網址](https://cssgradient.io/) ```css= .background { background-image: linear-gradient(to right, #6a11cb, #2575fc); height: 100vh; display: flex; justify-content: center; align-items: center; } .regLogin-form { background: white; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); width: 450px; } input[type="text"], input[type="email"], input[type="password"] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ccc; border-radius: 5px; } .action-links { display: flex; } .submit-button { width: 100%; padding: 10px; background-color: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; } .submit-button:hover { background-color: #45a049; } .back-button { width: 25%; padding: 10px; background-color: #f44336; color: white; border: none; border-radius: 5px; cursor: pointer; } .back-button:hover { background-color: #d32f2f; } .next-link { display: block; text-align: center; margin-top: 20px; color: #2575fc; } ``` * 建立HTML ```html= <script> <link href="./assets/css/custom-regLogin.css" rel="stylesheet"> </script> <body class="background"> <div> <div class="regLogin-form"> <h2><b>使用者註冊</b></h2> <input type="text" placeholder="Username" id="userName"> <input type="email" placeholder="Email" id="userMail"> <input type="password" placeholder="Password" id="userPwd1" > <input type="password" placeholder="Confirm Password" id="userPwd2" > <div class="action-links"> <button type="button" class="back-button" onclick="">返回</button>&emsp; <button type="bitton" class="submit-button" id="submitBtn">註冊</button> </div> <a href="./login.html" class="next-link">您已經有註冊會員了?</a> </div> </div> </body> ``` ### 註冊程式 * Swal官網 [官網連結](https://sweetalert.js.org/) * 加上Swal(取代alert) ```html= <head> <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> </head> ``` * JS程式 ```jS= <script> function register(){ const userName=$("#userName").val(); const userMail=$("#userMail").val(); const userPwd1=$("#userPwd1").val(); const userPwd2=$("#userPwd2").val(); let err=0; let errTxtA="",errTxtB=""; if(userPwd1!=userPwd2){ err++; errTxtA+="兩次的密碼輸入不同"; } if(!userName || !userMail || !userPwd1 || !userPwd2){ err++; if(errTxtA!=""){ errTxtB="、"; } errTxtB+="您輸入的內容有空值"; } if(err>0){ swal(errTxtA+""+errTxtB); }else{ $.ajax({ type: "post", data:{userName:userName,userMail:userMail,userPwd1:userPwd1}, url: "./prg/register.php", success: function(result, status) { var obj = JSON.parse(result); if(obj[0]==true){ swal(obj[1]); location.href = './login.html'; }else{ swal(obj[1]); } }, error: function() { alert('Internal Server Error'); } }); } } $(document).ready(function() { $("#submitBtn").on( "click", function() { register(); }); }); </script> ``` * PHP程式碼 ```PHP= <?php header("Access-Control-Allow-Origin: *"); require './connectdb.php'; $userName=trim($_POST["userName"]); $userMail=trim($_POST["userMail"]); $userPwd=trim($_POST["userPwd1"]); $mdata=array(); $today=date("Y-m-d H:i:s"); $count = $database->query("SELECT count(id) as CNT FROM `student_member` WHERE `userMail` = '$userMail'")->fetchAll(); //print_r($count); if($count[0]['CNT']>0){ $data="電子信箱已註冊!"; array_push($mdata,false,$data); echo json_encode($mdata); }else{ //在php查看加密方式 $cipher = "aes-128-cfb"; if (in_array($cipher, openssl_get_cipher_methods())) { //key&iv可以自己訂 $key = "ABCDEFG@2024"; $iv = "ABCDEFG@2024"; $password = openssl_encrypt($userPwd, $cipher, $key, $options=0, $iv); $database->query("INSERT INTO `student_member` (`id`, `userName`, `userMail`, `userPwd`, `createTime`) VALUES (NULL, '".$userName."', '".$userMail."', '".$password."', '".$today."');"); $finalId = $database->id(); if($finalId){ $data="新增成功!"; array_push($mdata,true,$data); echo json_encode($mdata); }else{ $data="新增有誤!"; array_push($mdata,false,$data); echo json_encode($mdata); } } } ?> ``` <b>[練習]</b> 1. 兩個密碼若不同,需要直接在畫面上呈現錯誤訊息,而不是按下按鈕才出現錯誤訊息(請用Jquery change) 2. 輸入完電子信箱,需要直接呈現是否可以註冊,可以註冊為綠色字樣,不能註冊請用紅色字樣。 ## 登入練習 ### 資料庫 * 使用資料庫: 1. 比對我們的user註冊的資料庫,比對密碼。 2. 紀錄使用者登入,並且給予一組亂數作為token。 * 建立使用者登入的資料表 ![image](https://hackmd.io/_uploads/S1Tm3XDm0.png) ### 登入畫面 * 建立HTML ```html= <body class="background"> <div> <div class="regLogin-form"> <h2><b>使用者登入</b></h2> <input type="email" placeholder="Email" id="userMail" > <input type="password" placeholder="Password" id="userPwd"> <div class="action-links"> <button type="button" class="back-button" onclick="window.history.back();">返回</button>&emsp; <button type="bitton" class="submit-button" id="submitBtn">登入</button> </div> <a href="./register.html" class="next-link">您並未有會員帳號?</a> </div> </div> </body> ``` ### 登入程式 * JS程式 ```JS= <script> function login(){ const userMail=$("#userMail").val(); const userPwd=$("#userPwd").val(); if(userMail && userPwd){ $.ajax({ type: "post", data:{userMail:userMail,userPwd:userPwd}, url: "./prg/login.php", success: function(result, status) { var obj = JSON.parse(result); if(obj[0]==true){ sessionStorage.setItem('token',obj[2]); sessionStorage.setItem('userName',obj[3]); swal(obj[1]).then((value) => { location.href = './adminLogin.html'; }); }else{ swal(obj[1]); } }, error: function() { alert('Internal Server Error'); } }); } } $(document).ready(function() { $("#submitBtn").on( "click", function() { login(); }); }); </script> ``` * PHP程式 ```PHP= <?php header("Access-Control-Allow-Origin: *"); require './connectdb.php'; function generateRandomStr($length) { $bytes = openssl_random_pseudo_bytes($length); return bin2hex($bytes); } //從jquery傳過來的數值 $userMail=trim($_POST["userMail"]); $userPwd=trim($_POST["userPwd"]); $mdata=array(); $today=date("Y-m-d H:i:s"); $cipher = "aes-128-cfb"; //透過傳過來的數值(帳號),找到對應的密碼 $oldPwd = $database->query("SELECT `id`,`userName`,`userPwd` FROM `student_member` WHERE `userMail` = '$userMail'")->fetchAll(); $key = "ABCDEFG@2024"; $iv = "ABCDEFG@2024"; //將該密碼做解碼變成明碼 $chkPwd = openssl_decrypt($oldPwd[0]["userPwd"], $cipher, $key, $options=0, $iv); if($chkPwd===$userPwd){//與輸入的密碼和明碼做對應 $token=generateRandomStr(30);//亂碼 $userId=$oldPwd[0]['id']; $userName=$oldPwd[0]['userName']; //查看是否有對應的登入紀錄 $oldInfo = $database->query("SELECT `id`,`userId`,`userName` FROM `student_login` WHERE `userId` = ".$userId." AND `userName` = '".$userName."' ")->fetchAll(); $err=0; if(count($oldInfo)>0){ //有登入紀錄,就把登入紀錄的token&登入時間資料做更新 $oldId=$oldInfo[0]["id"]; $info=$database->query("UPDATE `student_login` SET `token`='".$token."',`loginTime`='".$today."' WHERE `id` = ".$oldId.""); //確認更新是否有成功 $updtInfo=$info->rowCount(); if(!$updtInfo){ $err++; } }else{ //無登入紀錄,就把新增登入紀錄 $database->query("INSERT INTO `student_login` (`id`, `userId`, `userName`, `token`, `loginTime`) VALUES (NULL, '".$userId."', '".$userName."', '".$token."', '".$today."');"); //確認新增是否有成功 $finalId = $database->id(); if(!$finalId){ $err++; } } if($err==0){ $data="登入成功!"; array_push($mdata,true,$data,$token,$userName); echo json_encode($mdata); }else{ $data="登入有誤!"; array_push($mdata,false,$data,$token,$userName); echo json_encode($mdata); } }else{ $data="登入有誤!"; array_push($mdata,false,$data); echo json_encode($mdata); } ?> ``` 資料庫更新sql語法: ![image](https://hackmd.io/_uploads/ByQ50Ev7R.png) ### 登入後頁面 * 頁面建立 ```HTML= <!DOCTYPE html> <html lang="zh-tw"> <head> <title>class110上課練習</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> </head> <body > <div class="container"> <div class="col-4 mt-4"> <div class="card shadow"> <div class="card-body"> <h4 class="card-title"><b>歡迎使用者登入</b></h4> <p class="card-text">使用sessionStorage作為登入。</p> <button type="button" class="btn btn-outline-dark px-4" onclick="window.history.back();">返回</button>&emsp; </div> </div> </div> </div> </body> </html> ``` * 程式說明: 1. 需要確認是否有sessionStorage "token",若沒有直接返回登入頁面。 2. 確認該token是否有在資料庫內。 * PHP程式 若有做註冊change(確認mail是否可以註冊)的功課,可以拿那一個程式來做修改。 ```JS= <?php header("Access-Control-Allow-Origin: *"); require './connectdb.php'; $mdata=array(); $token=trim($_POST["token"]); $count = $database->query("SELECT count(id) as CNT FROM `student_login` WHERE `token` = '$token'")->fetchAll(); if($count[0]['CNT']>0){ array_push($mdata,true); echo json_encode($mdata); }else{ array_push($mdata,false); echo json_encode($mdata); } ?> ``` * JS程式 ```JS= <script> function chkLogin(){ var token=sessionStorage.getItem("token"); if(token!==null){ $.ajax({ type: "post", data:{token:token}, url: "./prg/chkLogin.php", success: function(result, status) { var obj = JSON.parse(result); if(obj[0]==false){ swal({title:"重新登入",icon:"error"}).then((value) => { location.href = './login.html'; },"error"); } }, error: function() { alert('Internal Server Error'); } }); }else{ swal({title:"重新登入",icon:"error"}).then((value) => { location.href = './login.html'; },"error"); } } $(document).ready(function() { chkLogin(); }); </script> ``` ## 登出 在登入後的頁面加上Navbar,並呈現登出按鈕 & 使用者名稱 * HTML頁面 ```html= <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="./adminLogin.html"><b>Learn</b>_後臺管理</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse justify-content-end" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <span class="nav-link" id="loginName"></span> </li> <li class="nav-item"> <a class="nav-link" href="#" onclick="logOut()">登出</a> </li> </ul> </div> </div> </nav> ``` * JS程式 ```JS= function logOut(){ var token=sessionStorage.getItem("token"); if(token!==null){ $.ajax({ type: "post", data:{token:token}, url: "./prg/clearLogin.php", success: function(result, status) { var obj = JSON.parse(result); if(obj[0]==true){ swal({title:"您已登出",icon:"info"}).then((value) => { location.href = './login.html'; },"error"); //清理所有的sesionStorage sessionStorage.clear(); } }, error: function() { alert('Internal Server Error'); } }); } } $(document).ready(function() { //呈現userName在navbar上 $("#loginName").html(sessionStorage.getItem("userName")); }); ``` * PHP程式 ```PHP= <?php header("Access-Control-Allow-Origin: *"); require './connectdb.php'; $mdata=array(); $token=trim($_POST["token"]); $info=$database->query("UPDATE `student_login` SET `token`='' WHERE `token` = '".$token."'"); //確認更新是否有成功 $updtInfo=$info->rowCount(); if(!$updtInfo){ $err++; } if($err==0){ array_push($mdata,true); echo json_encode($mdata); }else{ array_push($mdata,false); echo json_encode($mdata); } ?> ```