簡介

製作留言版主頁、新增留言、登入頁面切版、註冊頁面切版。

規劃產品路由及功能

  • index.php: 觀看所有留言
  • handle_add_comment.php: 「新增」留言

切版

切出留言板的頁面。

送出並發布留言

思考流程
按下「Submit」按鈕 → 將輸入的資料放進MySQL 資料庫 → 從 MySQL 取出 → 在 index.php 發布留言

製作步驟

Step 1. 抓取提交表單的輸入內容

index.php

 <form method='POST' action='handle_add_comment.php'>
     <span>Nickname:</span>
     <input type='text' name='nickname'></input>
     <textarea name='content'></textarea>
    <input type='submit' value='Submit'></input>
</form>

handle_add_comment.php

<?php
    $nickname = $_POST['nickname'];
    $content = $_POST['content'];
?>


Step 2. 連結 MySQL 資料庫 & 顯示連結錯誤訊息

handle_add_comment.php

<?php
require_once('conn.php');
$result = $conn->query('SELECT * FROM jean_users');
if (empty($result)) {
  die($conn->error);
}
?>

conn.php
usernamepassworddbname 中隨便寫個錯誤,偵測有沒有跳出錯誤訊息。

<php?
$username = '<username>';
$password = '<password>';
$dbname = '<錯誤的dbname>';
$conn = new mysqli($servername, $username, $password, $dbname);
if (!empty($conn->connect_error)) {
   die('資料庫連線錯誤' . $conn->connect_error);
}
?>

結果:
成功偵測如下:


Step 3. 將表單輸入內容放入 MySQL 中

錯誤想法:
handle_add_comment.php

// 從表單抓取輸入值 
$nickname = $_POST['nickname'];
$content = $_POST['content'];
// [ERRROR!!!] 將表單輸入值放入 db
$result['nickname'] = $nickname;
$result['content'] = $content;

正確作法:
handle_add_comment.php

<?php
  // 抓取表單提交的輸入內容
  $nickname = $_POST['nickname'];
  $content = $_POST['content'];

  // 將留言內容放入 MySQL 資料庫內
  $sql = sprintf(
    "insert into jean_comments(nickname, content) values('%s', '%s')",
    $nickname,
    $content
  );
  $result = $conn->query($sql);

  // 偵測 MySQL 有沒有正確新增資料
  if (!$result) {
    die($conn->error);
  }

  // 頁面自動跳轉回 index.php
    header("Location: index.php");
?>

犯的小錯誤:

  1. 放入 MySQL 有 MySQL 自己一套的輸入語法,不能用自己的想法來寫,要按照 MySQL 程式的邏輯寫。
  2. sprintf() 用法:
    其中:
    (1) jean_comments<dbTable>nicknamecontent 為該 <dbTable> 內參數資料的欄位名稱。
    (2) %ssprintf 替代的變數輸入代號,不同字母分別代表不同形式,如 %s 表字串形式、%d 表十進制數。
    (3) 另存 $sql 變數的原因是,可以增加可讀性,也易於修改及維護。
    sprintf(
     "insert into jean_comments(nickname, content) values('%s', '%s')",
     $nickname,
     $content
    );
    

Step 4. 在 index.php 顯示送出的留言內容

  1. 從資料庫撈資料 v.s. 取用資料在 php 使用

    • 從資料庫撈資料
      $result = $conn->query(新增、刪除、修改、搜尋);
      僅是從資料庫裡面撈資料,若需要進一步在 php 使用,需要參考下一個「取用資料」。

    • 取用資料 & 在 php 使用
      $row = $result->fetch_assoc();
      而且一次取用一筆,所以可以使用 while 判斷是否有資料(true or false),true 的話,就取用資料。

  2. 知道怎麼取資料後,要怎麼讓 index.php 可以顯示發布的留言呢?

  • handle_add_comment.php:將表單提交的輸入內容放入 MySQL 裡,並撈出資料。(在Step. 3
  • index.php:從 MySQL 中取用資料,並發布留言。
    利用 php 特性(<?php ... > 才能執行 php,在這個以外的可以使用 html tag

        (1) @ index.php 利用 php 語法來連結資料庫,從 dbTable (jeans__comments) 撈資料,並判斷有沒有成功取得資料。

<?php
  require_once('conn.php');  //連結資料庫

 // 從 db 撈取資料,並判斷有無錯誤訊息。
  $result = $conn->query("select * from jean_comments order by id desc");
  if (!$result) {
    die('Error:' . $conn->error);
  }
?>

        (2) @ index.php 拿取並使用 dbTable 內的資料,用於顯示所有的留言。

<?php
while ($row = $result->fetch_assoc()) {
?>

  html tags 穿插放入 php語法: <?php nickname in db ?>, <?php created_at in db ?>, <?php content in db?>

<?php } ?>

撈好資料,就可以使用 $row = $result->fetch_assoc() 來取得資料並在 php 中使用,不過這只有取得一行資料,若要取得所有資料的筆數,可以使用 while 判斷 $result->fetch_assoc() 存在(true)。

  1. 成功加上新增留言的功能後,要 debug,例如:沒有填寫完整的話,要提示然後填寫完整才可以新增留言
    (1) 判斷 nickname 與 content 的是否為空。
         a. 是 @ index.php 裡面寫判斷式呢?
         b. 還是 @ handle_add_comment.php 裡面寫判斷式呢?
         因為需要在 index.php 顯示「資料輸入不正確,請填寫完整」,所以我覺得應該是放在 index.php 內。
      
    (2) 第一次嘗試
    <h1>Comment</h1>
    <?php
    if(empty($_POST['nickname']) ||empty($_POST['content'])) {
    $msg = '資料錯誤請重新填寫';
    ?>
    <h2><?php echo $msg ?></h2>
    <?php } ?>
    

        (3) 第二次嘗試
我覺得好像不能在 index.php 判斷,我突然想起來範例影片好像是在 handle_add_comment.php 利用 header 將其導到一個錯誤的網址(例如:https://... index.php?errCode=1,然後再在 index.php 判斷網址上的 errCode 寫判斷式顯現「資料輸入不齊全」。

             a. 先在 handle_add_comment.php 判斷兩個輸入框是否有空,若有空的話,利用 header 導入一含有 query string 的網址——https:// ... index.php?errCode=1,並使用 die() 結束執行。

              b. 在 index.php 判斷 errCode 是否存在、是否為 1,是的話,就顯現「<h3> 資料輸入不齊全</h3>

handle_add_comment.php 流程問題:

問題敘述:「判斷輸入框是否為空」應該放在前半部,還是放在 code 結尾?

  • 狀況 1:「判斷輸入框是否為空」放在後半部:
    這樣的話,會先把輸入框內容放入資料庫後,才判斷輸入框是否為空。意思就是:當資料被放入 MySQL 後,就會被 index.php 中 $conn->fetch_assoc() 讀取,也就是說會被發布到留言中,所以這個方法行不通。

  • 狀況 2:「判斷輸入框是否為空」放在前半部:
    先判斷是否為空,為空的話,就連資料都不要 key 進 MySQL,這樣才能有效偵測輸入不完全的資料被新增到 MySQL 裡面。

錯誤:「判斷輸入框是否為空」放在後半部

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

    $nickname = $_POST['nickname'];
    $content = $_POST['content'];
    // 將輸入的內容放入 MySQL
  $sql = sprintf(
    "insert into jean_comments(nickname, content) values('%s', '%s')",
    $nickname,
    $content
  );
  $result = $conn->query($sql);

  // 判斷輸入框是否為空
  if (empty($_POST['nickname']) 
    || empty($_POST['content'])) {
    header("Location: index.php?errCode=1");
    die('資料不齊全');
}
    header("Location: index.php");

?>


正確:「判斷輸入框是否為空」放在前半部

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

// 判斷輸入框是否為空
if (empty($_POST['nickname']) 
    || empty($_POST['content'])) {
    header("Location: index.php?errCode=1");
    die('資料不齊全');
}

// 將輸入框的資料新增至 MySQL
    $nickname = $_POST['nickname'];
    $content = $_POST['content'];

  $sql = sprintf(
    "insert into jean_comments(nickname, content) values('%s', '%s')",
    $nickname,
    $content
  );
  $result = $conn->query($sql);

  if (!$result) {
    die($conn->error);
  }

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

index.php 遇到的小問題:怎麼把漏填寫輸入框的錯誤訊息提示印出來?

問題敘述: 要怎麼把 <h3> 放在 <?php ... ?> 裡面?

錯誤想法:將 <h3>php code 分開
這樣一來,不論在 php 內怎麼寫判斷式, index.php 始終會顯現(echo$msg = '資料錯誤請重新填寫'

<!-- index.php -->
<h1>Comment</h1>
<?php
  if(empty($_POST['nickname']) ||empty($_POST['content'])) {
  $msg = '資料錯誤請重新填寫';
?>
<h2><?php echo $msg ?></h2>
<?php } ?>




正確想法:將 <h3> 寫在 php code 的字串內
寫在字串內的話,就會直接在瀏覽器 echo 出 <h3>資料錯誤請重新填寫</h3>,然後在瀏覽器 render 的時候,會把 <h3> 變成 html 標籤,如此一來,判斷式就完成判斷,並印出錯誤訊息。
另外補充:為什麼要多判斷一次 $code = 1 呢?因為可以套用在其他偵測可能會有多個錯誤的地方,也許該錯誤不只一個,有二到三個,這樣就可以用 $code = '1', '2', '3',如此一來,多判斷一次 errCode 為何數值,就可以使用同一個判斷式,只要再增加 else if...,利用「登入」的功能來舉例: else if ($code == '2' ) { echo '密碼錯誤'} else if ($code == '3' { echo '無此帳號'})

<form class='board__new-comment-form' method='POST' action='handle_add_comment.php'>
<h1>Comment</h1>
<?php
  if (!empty($_GET['errCode'])) {
    $code = $_GET['errCode'];
    $err = 'Err!!!';
    if ($code === '1') {
      $msg = '資料輸入不齊全';
    }
echo '<h2 class="error">Error:' . $msg . '</h2>';
 }
?>

index.php 遇到的小問題:
使用 query string 導到錯誤頁面,那怎麼取出 query string 的錯誤訊息?因為 form 提交是使用 POST method,但是 index.php?errCode=1 也不是被表單提交呀!好像不能使用 $_POST 取得 errCode 的 value,應該是哪裡觀念漏掉!

後來想起來了!在 GET method 中使用表單提交,輸入的參數會以 query string 的方式存在網址上,若要取得 query string 的值(value),在 php 內可以使用 $_GET['參數'],而此時query string 網址的參數便是 errCode,?值為 1,這樣就可以實現:在 handle_add_comment.php 執行「表單送出」的動作,同時偵測有沒有輸入框都填寫;同時利用 query string 的方法,將 query 傳給 index.php,然後在 index.php 中就可以利用 query string 得到 handle_add_comment.php 判斷輸入框皆填寫的結果。

規劃會員路由及功能

  • register.php:註冊頁面(實際看得到的頁面)
  • login.php:登入頁面(實際看得到的頁面)
  • logout.php:登出(功能,沒有頁面)
  • handle_register.php:處理註冊邏輯(功能,沒有頁面)
  • handle_login.php:處理登入邏輯(功能,沒有頁面)

切版

register.php

因為是從 index.php 複製過來的檔案,我發現在 class 命名上不能太客製化,可能在 index.php 是 new-comment,但是在 register.php 只是一個 box,或者是在 index.php 的 nickname 輸入框 class='board__input-nickname',但是在 register.phpusername、password、nickname 的文字輸入框,就得每個都命名一個 class='board__input-xxx',這樣其實不是一個好命名,因為需要在 style.css 在不同 class 中增加一樣的樣式,而且在不同的 php 檔案裡面,可能樣式有小小的不同,這樣只要有一點不同,就創新的 class,其實滿亂的,後來就在想可不可以改成:文字輸入框相同的 CSS 樣式,就把 class 命名為 'board__input',如果有個別需要的 CSS 樣式,再另外新增 class:如在註冊頁面的文字輸入框需要置中,所以我可能需要新的 class 來設定 CSS 樣式,就可以命名為'board__input-register',這樣一來,就可以盡量把相同的樣式跟不同的樣式分開,而且這樣就不會把 class 樣式複雜化。

我後來再翻看影片範例的 class 屬性,後來發現其實不管文字輸入框是在 username、nickname、password,好像都是同一個 class='board__nickname',沒有特別更改,但也因此沒有造成在複製舊頁面,製作新頁面時發生 class 太複雜的困擾。

這表示我的 class 命名方式可以再改進。

#board #PHP #MySQL







Related Posts

[JS102] npm, Jest, ES6  &[ALG101]

[JS102] npm, Jest, ES6 &[ALG101]

筆記、Single Page Application

筆記、Single Page Application

[25] 強制轉型 - 隱含的強制轉型、Addition Operator、Strings <> Numbers

[25] 強制轉型 - 隱含的強制轉型、Addition Operator、Strings <> Numbers






Comments