留言板、新增功能篇--(編輯、刪除)


Posted by s103071049 on 2021-06-22

1.編輯暱稱 2.編輯留言 3.刪除留言 4.分頁功能

編輯暱稱功能

各式作法:

  1. 放一個編輯暱稱鈕,點擊後連到新的頁面,輸入暱稱按提交就可以更新暱稱
  2. 直接在頁面放表單

先放入相對應的 input

<h3 class='greeting__word'>你好,<?php echo $nickname?>(^ω^)</h3>
    <form action="update_user.php" method="POST">
        新的暱稱:<input type="text" name="nickname">
        <input type="submit">
    </form>

調整樣式

<form action="update_user.php" method="POST" class="message">
    <div>新的暱稱 : <input type="text" name="nickname" class='register_input'></div>
    <input type="submit" class="submit__btn">
</form>

處理 update_user.php,將它命名的更好一點,變成 handle_update_user.php。

如果沒有 nickname 的話,進行錯誤處理顯示資料不齊全。
有 nickname 去資料庫改 nicknames。

<?php
  require_once('conn.php');
  session_start();
  $nickname = $_POST['nickname'];
  if (empty($nickname)) {
    header('Location: main.php?errCode=1');
    die('資料未輸入完整');
  }
  $username = $_SESSION['username'];
  $sql = 'update users set nickname=? where username=?';
  $stmt = $conn->prepare($sql);
  $stmt->bind_param("ss", $nickname, $username);
  $result = $stmt->execute();
  if (!$result) {
    die($conn->error);
  }
  header('Location: main.php');
?>

調整放置位置

<?php if (empty($username)) {?>
    <a href="login.php"><span>登入</span></a>
    <a href="register.php"><span>註冊</span></a>
    <?php  } else {?>
    <a href="logout.php"><span>登出</span></a>
    <a href="#" class="board__nickname"><span>編輯暱稱</span></a>
<?php } ?>
</div>
    <div class='desc'>
      <h2 class='title'>Comments</h2>
      <h3 class='greeting__word'>你好,<?php echo $nickname?>(^ω^)</h3>
    <form action="handle_update_user.php" method="POST" class="message hide board__nickname-form">
                <div>新的暱稱 : <input type="text" name="nickname" class='register_input'></div>
                <input type="submit" class="submit__btn">
                <hr>
    </form>

加上 js,點擊按鈕展開、不展開的設計

let btn = document.querySelector('.board__nickname')
btn.addEventListener('click', (e) => {
  let form = document.querySelector('.board__nickname-form')
  let textareaForm = document.querySelector('.board__add__comment-form')
  form.classList.toggle('hide')
  if (!form.classList.contains('hide')) {
    textareaForm.classList.add('hide')
  } else {
    textareaForm.classList.remove('hide')
  }
})

因為 comments 資料寫死了,所以編輯暱稱結束後,下面已經留過的言的暱稱不會一併更新。

資料庫正規化簡介

comments表中將 nickname 放入,如果我的 users 表改了 nickname 就無法同步更新。應該放 user_id 或 username 跟 users 表做關聯。

將資料庫重新整理過,去除依賴關係產生關連,就叫資料庫正規化。

調整 handle_add_comment.php

<?php
  require_once('conn.php');
  session_start();
  require_once('utils.php');
  $username = $_SESSION['username'];
  $content = $_POST['message__box'];

  if (empty($content)) {
    header('Location: main.php?errCode=1');
    die('未輸入內容');
  }

  $sql ='insert into comments(username, content) values(?, ?)';
  $stmt = $conn->prepare($sql);
  $stmt->bind_param('ss', $username, $content);
  $result = $stmt->execute();
  if(!$result) {
    header('Location: main.php?errCode=2');
    die ('Error' . $conn ->error);
  }
  header('Location: main.php');
?>s

資料庫 schema 參考

SQL join 語法介紹

要如何讓 users 和 comments 表利用 username 進行關聯。兩個表單之間的關聯會使用 SQL join

一般來說,最常用 left join。select * from comments left join users on comments.username = users.username
可以再細調 order by comments.id desc

會保留 comments 的內容,去找 users 的資料。
visual join

因為這樣改 main.php 資料會被覆蓋,所以需要幫資料表另取別名

  $stmt = $conn->prepare(
    'select * from comments ' . 
    'left join users on comments.username = users.username ' . 
    'order by comments.id desc');
  $stmt = $conn->prepare(
    'select ' .
      'C.id as id, C.content as content, C.create_at as create_at, ' .
      'U.nickname as nickname, U.username as username ' .
    'from comments as C ' . 
    'left join users as U on C.username = U.username ' . 
    'order by C.id desc');
# 這樣寫是因為用 * 會有欄位被覆蓋的問題

處理暱稱相同,辨識問題

<span class='nickname'>
    <?php echo escape($row['nickname'])?>
    (@<?php echo escape($row['username'])?>)
</span>

編輯留言功能

一、先加編輯留言的按鈕 <a href="update_comment.php?id=<?php echo $row['id']?>" >編輯</a>
二、限定只能編輯自己留言

<?php if ($username === $row['username']) {?>
  <a href="update_comment.php?id=<?php echo $row['id']?>" >編輯</a>
<?php }?>

三、製作 update_comment.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HW8 留言板</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class='warning'>
        注意!本站為練習用網站,因教學用途刻意忽略資安的實作, 註冊時請勿使用任何真實的帳號或密碼。
    </div>
    <div class='content'>
        <div class='desc'>
            <h2 class='title'>編輯留言</h2>
            <h3 class='greeting__word'>你好,<?php echo $nickname?>(^ω^)</h3>
            <?php
                if (!empty($_GET['errCode'])) {
                  $errCode = $_GET['errCode'];
                  $msg = 'err';
                  if ($errCode === '1') {
                    $msg = '請輸入內容再提交 !';
                   }
                  echo '<h2 class="error__word-noContent"> 錯誤 : ' . $msg .'</h2>';
                }
            ?>
        </div>
        <form method="POST" action="handle_update_comment.php" class='message board__update__comment-form'>
            <textarea name="message__box" id="message__box" rows="10"></textarea>
            <input type="submit" name="submit" class="submit__btn">
          <hr>
        </form>
    </div>
</body>
</html>

四、編輯留言欄位,要出現原本的留言
透過 get 傳進來的 id,找到 comments,把它的內容抓出來,echo 到 textarea 的位置

<?php
  require_once('conn.php');
  require_once('utils.php');
  session_start();
  $id = $_GET['id'];
  $stmt = $conn->prepare(
    'select * from comments where id = ?'
  );
  $stmt->bind_param('i', $id);
  $result = $stmt->execute();
  if (!$result) {
    die('錯誤訊息 : ' . $conn ->error);
  }
  $result = $stmt->get_result();
  $row = $result->fetch_assoc();
?>
<textarea name="message__box" id="message__box" rows="10"><?php echo $row['content']?></textarea>

五、製作隱藏鈕,帶 id 值到 handle_update_comment.php
按下表單,handle_update_comment.php 需要知道按的是哪個 id

<input type="hidden" name="id" value="<?php echo $row['id']?>"/>

六、製作 handle_update_comment.php
直接 copy handle_update_users.php 進行修改

先調整 update_comment.php => name="content"

<textarea name="content" id="message__box" rows="10"><?php echo $row['content']?></textarea>

檢視有無 content,若無進行錯誤處理
handle_update_comment.php

<?php
  require_once('conn.php');
  session_start();
  $content = $_POST['content'];
  if (empty($content)) {
    header('Location: update_comment.php?errCode=1&id='.$_POST['id']);
    die('資料未輸入完整');
  }
  $username = $_SESSION['username'];
  $id = $_POST['id'];
  $sql = 'update comments set content=? where id=?';
  $stmt = $conn->prepare($sql);
  $stmt->bind_param("si", $content, $id);
  $result = $stmt->execute();
  if (!$result) {
    die($conn->error);
  }
  header('Location: main.php');
?>

刪除留言功能

一、製作刪除鈕

<a href="update_comment.php?id=<?php echo $row['id']?>" class="revise_btn">&emsp;編輯</a>
<a href="delete_comment.php?id=<?php echo $row['id']?>" class="revise_btn">&ensp;刪除</a>

二、製作 delete_comment.php

hard delete

真的從資料庫中刪除。

<?php
  require_once('conn.php');
  $id = $_GET['id'];
  if (empty($id)) {
    header('Location: main.php?errCode=1');
    die('資料未輸入齊全');
  }
  $sql ='delete from comments where id=?';
  $stmt = $conn->prepare($sql);
  $stmt->bind_param("i",$id);
  $result = $stmt->execute();
  if (!$result) {
    die($conn->error);
  }
  header('Location: main.php');
?>

soft delete

不會真的從資料庫中刪掉,只是畫面看起來像是刪掉。

從資料庫 comments 表新增一個欄位:isdeleted 如果是 1 表示刪掉,是 0 表示沒刪。目的是怕誤刪資料,有一天無法復原。

調整代碼,在 update 將 is_deleted 設成 1

$sql ='update comments set is_deleted=1 where id=?';

改 main.php
寫 query 時先用 left join 再用 where 將資料篩選出來。

  $stmt = $conn->prepare(
    'select ' .
      'C.id as id, C.content as content, C.create_at as create_at, ' .
      'U.nickname as nickname, U.username as username ' .
    'from comments as C ' . 
    'left join users as U on C.username = U.username ' .
    'where C.is_deleted is Null ' .
    'order by C.id desc');

#form #SQL #PHP







Related Posts

How To Crack Data Science Interview

How To Crack Data Science Interview

命題邏輯(Propositional Logic)

命題邏輯(Propositional Logic)

串接 API -- try catch 練習

串接 API -- try catch 練習


Comments