---
# System prepended metadata

title: 5-6 、 規劃會員功能和路由
tags: [Lidemy心得, 進度筆記, BE101, PHP, 2020十月第四周]

---

# 5-6 、 規劃會員功能和路由
###### tags: `BE101` `PHP` `2020十月第四周` `進度筆記` `Lidemy心得`  

---

==因為留言板通常是開放給會員留言評論，並且避免機器人留言，因此新增會員要有:==
- 註冊、登入和登出功能。 

---
## 會員功能的需求處理檔案 
- 需要註冊頁面的功能: register.php 註冊頁面==(可見)==。 
- 在頁面中處理"提交"這個 `功能性` 的是 handle_add_comment.php 檔案。 
- ==可見==的登入表單 (login.php)；以及 `功能性` 的處理登入的邏輯驗證(handle_login.php) 。 
- `功能性` logout.php 檔案，登出後導回首頁。 
- 因此 `功能性` 的檔案沒有頁面，==可見==的頁面給 User 看。 

***

# 5-7 、 規劃會員資料結構以及建置  
###### tags: `BE101` `PHP` `2020十月第四周` `進度筆記` `Lidemy心得`  

---
在 phpMyAdmin 中新增會員功能: 
ID(AUTO_INCREMENT) 、 username(varchar(64)) 、 password(varchar(128)) 、 nickname(註冊暱稱 、 varchar(64)) 、 create_at(何時建立 、 datetime) 。  

***

# 5-8 、 實作註冊功能  
###### tags: `BE101` `PHP` `2020十月第四周` `進度筆記` `Lidemy心得`  

---

## index 主頁和版型
在 index.php 檔案中從 `<main class="board">` 底下新增一個分區:   
```
      <div>
        <a class="board__btn" href="register.php">註冊</a>
        <a class="board__btn" href="login.php">登入</a>
      </div>
```

style.css 中則是更改樣式:  
```
.card__time {
  color: #a0a0a0;
}

.board__btn {
  padding: 10px 30px;
  border: 1px solid #c2dffb;
  border-radius: 5px;
  color: black;
  font-size: 16px;
  background: white;
  min-width: 20px;
  text-decoration: none;
  display: inline-block;
```

- 注意 `display: inline` 和 `display: inline-block` 會影響註冊和登入的按鈕(也可以調整 padding)。  

- 整體版面的版型 ， padding 會影響版面擴張，一樣用 `display: inline-block` 調整寬高。 

***

## 註冊頁面  

- 注意 POST 動作是抓 `handle_register.php` 因此在 `register.php` 中新增: 
```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>留言板</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <header class="warning">
    <strong>注意！本站為練習用網站，因教學用途刻意忽略資安的實作，註冊時請勿使用任何真實的帳號或密碼。</strong>
  </header>
  <main class="board">
      <div>
        <a class="board__btn" href="index.php">回留言板</a>
        <a class="board__btn" href="login.php">登入</a>
      </div>
      <h1 class="board__title">註冊</h1>
      <?php
        if (!empty($_GET['errCode'])) {
          $code = $_GET['errCode'];
          $msg = 'Error';
          if ($code === '1') {
            $msg = '資料不齊全';
          } else if ($code === '2') {
            $msg = '帳號已被註冊';
          }
          echo '<h2 class="error">錯誤：' . $msg . '</h2>';
        }
      ?>
      <form class="board__new-comment-form" method="POST" action="handle_register.php">
        <div class="board__nickname">
          <span>暱稱：</span>
          <input type="text" name="nickname" />
        </div>
        <div class="board__nickname">
          <span>帳號：</span>
          <input type="text" name="username" />
        </div>
        <div class="board__nickname">
          <span>密碼：</span>
          <input type="password" name="password" />
        </div>
        <input class="board__submit-btn" type="submit" />
      </form>
  </main>
</body>
</html> 
```

- 這個頁面刻好後會出現註冊頁面。  
- 密碼欄位記得 `<input type="password" name="password" />` 才會使密碼顯示星號。  

---

## 檢查註冊輸入資訊

- 刻好註冊頁面後，接下來是檢查註冊輸入資訊的寫法，新增一個 ` handle_register.php` 。  

```
<?php
  require_once('conn.php');

  if (
    empty($_POST['nickname']) ||
    empty($_POST['username']) ||
    empty($_POST['password']) 
  ) {
    header('Location: register.php?errCode=1');
    die();
  }

  $nickname = $_POST['nickname'];
  $username = $_POST['username'];
  $password = $_POST['password'];

  $sql = sprintf(
    "insert into users(nickname, username, password) values('%s', '%s', '%s')",
    $nickname,
    $username,
    $password
  );
  $result = $conn->query($sql);
  if (!$result) {
    $code = $conn->errno;
    if ($code === 1062) {
      header('Location: register.php?errCode=2');
    }
    die($conn->error);
  }

  header("Location: index.php");
?>
```

- nickname 、 username 、 password 都不能是空的。  
- 錯誤排除機制用 errorCode 排除；用 `sprintf` 好處是改東西方便。  
- 將 header 導回 `register.php?errCode=2` 。  
- 最後註冊完成後，用 header 帶資訊導回 index.php 。 
- 註冊完成後會將表單資料寫進資料庫的 table (才算成功)。 
- 一般來說 username 是不能重複，因此要設成唯一。 

***

## 避免帳號被重複註冊  
```
$result = $conn->query($sql);
  if (!$result) {
    if (strpos($conn->error, "Duplicate entry")
	  !== false) { 
      header('Location: register.php?errCode=2');
    }
    die($conn->error);
  }

  header("Location: index.php");
>?
```
- 如果資訊包含 "Duplicate entry" ， 我們就用 `errCode=2` 導回，否則就讓他 die (出現錯誤通知，如帳號已被註冊)。 
- 目前規則: 暱稱、密碼可以重複。 

==補充==  
```
這邊補充一下原本用 die($conn->errno) 沒有出現東西的原因

首先呢，die 跟 exit 這兩個 function 其實是一樣的

根據 exit 的文件：https://www.php.net/manual/en/function.exit.php

後面放的東西如果是數字的話，會被當作是一個錯誤的狀態碼然後不會被顯示出來（原本我在影片中猜測的是 HTTP status，但不是這樣），所以才會是空的

因此後面加上一個字串變成字串之後就會正常顯示出來了
```