2024/08/14
2024/11/07 (更新內容)
我們先從每一頁的基本要件開始。
insert.php:
<?php
require_once "header.php";
try {
require_once 'db.php';
$msg="";
?>
<?php
mysqli_close($conn);
}
//catch exception
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
require_once "footer.php";
?>
加入form的內容:
<div class="container">
<form action="insert.php" method="post">
<div class="mb-3 row">
<label for="_company" class="col-sm-2 col-form-label">求才廠商</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="company" id="_company" placeholder="公司名稱" required>
</div>
</div>
<div class="mb-3">
<label for="_content" class="form-label">求才內容</label>
<textarea class="form-control" name="content" id="_content" rows="10" required></textarea>
</div>
<input class="btn btn-primary" type="submit" value="送出">
<?=$msg?>
</form>
</div>
大家試試看
新增一筆資料的SQL是:
insert into job (company, content, pdate) values ('Apple', 'Programmer', '2019-08-29');
一般網路上的範例都是直接將$_POST的內容取代值,然後執行sql,但是為了避免sql injection,最好使用prepare (詳參: PHP Prepared Statements / mysqli_stmt_prepare)
為了使用prepare,我們需要將內容以變數取代,php的語法就是:
$sql="insert into job (company, content, pdate) values (?, ?, now())";
利用prepare去設定sql statement:
/* 產生一個 prepared statement */
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
利用prepare有很多好處,在這裡的最大功能是避免sql injection。(詳參: 【網頁安全】給網頁後端新人的 SQL Injection 介紹與防範 (PHP))
再利用bindParam去綁定變數內容以及sql中的變數
/* bind parameters for markers */
mysqli_stmt_bind_param($stmt, "ss", $company, $content);
執行execute()後會新增資料到資料庫。
/* 執行 */
mysqli_stmt_execute($stmt);
php的部分
$msg="";
if ($_POST) {
// insert data
$company = $_POST["company"];
$content = $_POST["content"];
$sql="insert into job (company, content, pdate) values (?, ?, now())";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "ss", $company, $content);
$result = mysqli_stmt_execute($stmt);
if ($result) {
header('location:query.php');
}
else {
$msg = "無法新增資料";
}
}
接下來我們在query.php新增一個Button,並讓Button留在畫面右下方。讓使用者可以點選並開啟insert.php。
<a href="insert.php" class="btn btn-primary position-fixed bottom-0 end-0">+</a>
由於我們設定了一個自動新增的欄位postid,我們就可以利用這個欄位來刪除資料,SQL是:
delete from job where postid=1;
我們就可以利用這個語法去刪除資料,對應的PHP語法是:
$sql="delete from job where postid=?";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "i", $postid);
$result = mysqli_stmt_execute($stmt);
接下來,我們來完成delete.php
<?php
try {
if ($_GET) {
require_once 'db.php';
//delete data
$postid = $_GET["postid"];
$sql="delete from job where postid=?";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "i", $postid);
$result = mysqli_stmt_execute($stmt);
mysqli_close($conn);
header('location:query.php');
}
else {
header('location:query.php');
}
}
//catch exception
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
?>
一般我們會在列出所有資料的時候,在資料後面讓使用者可以點選,並進行刪除。
修改query.php
<table class="table table-bordered table-striped">
<tr>
<td>求才廠商</td>
<td>求才內容</td>
<td>刊登日期</td>
<td></td>
</tr>
<?php
while($row = mysqli_fetch_assoc($result)) {?>
<tr>
<td><?=$row["company"]?></td>
<td><?=$row["content"]?></td>
<td><?=$row["pdate"]?></td>
<td><a href="delete.php?postid=<?=$row["postid"]?>" class="btn btn-primary">刪除</a>
</td>
</tr>
<?php
}
?>
</table>
刪除資料是個危險動作,有多種處理方式,一種是增加一個欄位「deleted」,不直接將資料刪除,而是將資料註記,未來在瀏覽資料時,排除這些資料。另一種寫法是將資料複製到另一個資料表,再將資料刪除。最基本的處理方式是讓使用者確認。
delete.php
<?php
require_once "header.php";
try {
$postid = "";
$company = "";
$content = "";
$pdate = "";
if ($_GET) {
require_once 'db.php';
$action = $_GET["action"]??"";
if ($action=="confirmed"){
//delete data
$postid = $_GET["postid"];
$sql="delete from job where postid=?";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "i", $postid);
$result = mysqli_stmt_execute($stmt);
mysqli_close($conn);
header('location:query.php');
}
else{
//show data
$postid = $_GET["postid"];
$sql="select postid, company, content, pdate from job where postid=?";
// $result = mysqli_query($conn, $sql);
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "i", $postid);
$res = mysqli_stmt_execute($stmt);
if ($res){
mysqli_stmt_bind_result($stmt, $postid, $company, $content, $pdate);
mysqli_stmt_fetch($stmt);
}
}//confirmed else
mysqli_close($conn);
}//$_GET
} catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
?>
<table class="table table-bordered table-striped">
<tr>
<td>編號</td>
<td>求才廠商</td>
<td>求才內容</td>
<td>刊登日期</td>
</tr>
<tr>
<td><?=$postid?></td>
<td><?=$company?></td>
<td><?=$content?></td>
<td><?=$pdate?></td>
</tr>
</table>
<a href="delete.php?postid=<?=$postid?>&action=confirmed" class="btn btn-primary">刪除</a>
<?php
require_once "footer.php";
?>
在資料庫裡user資料表,原本有兩個欄位
account VARCHAR(20) (Primary Key)
password VARCHAR(20)
並請新增5個帳號
更動user資料表:
role CHAR(1) 設為ASCII 就只需要1個byte
name VARCHAR(10)
created_at DATE
ALTER TABLE `user` ADD `role` CHAR(1) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT 'U' AFTER `password`, ADD `name` VARCHAR(20) NOT NULL AFTER `role`, ADD `created_at` DATE NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `name`;
請利用上週的登入介面,在登入介面中增加一個連結讓使用者可以註冊
請參考以上的範例及user資料表,寫一個註冊程式,讓使用者可以自行註冊
注意帳號不能重覆,如果重覆要提醒使用者