1. hw1_實作 API 新增留言
MTR05_第十二週(06/28 ~ 07/04):前後端整合_作業一帶著做之打造後端 API:Part1
流程:
a. 先引入連線
b. 引入 header('Content-Type: application/json;charset=utf-8');
把資料變成 json 格式
c. 錯誤處理:如果沒有 content, nickname, site_key 就回傳錯誤訊息
if (
empty($_POST['content']) ||
empty($_POST['nickname']) ||
empty($_POST['site_key'])
) {
$json = array(
"ok" => false,
"message" => "Please input missing fileds"
);
$response = json_encode($json);
echo $response;
die();
}
d. 把資料拿進來以後,新增到資料庫裡面
e. 如果沒有資料,做錯誤處理
f. 用 postman 做 API 測試,線上版的不能用,後來下載了桌面版的,在下面選 desktop agent,因為非同源政策的關係,不可以用瀏覽器版本的
遇到的困難:
- 跟著老師打程式碼,真的就是要細心!有些錯誤自己看半天都找不到,就這樣卡了一小時,沒關係,找到就好!(成功了真的好開心)
2. hw1_實作 API 顯示留言
MTR05_第十二週(06/28 ~ 07/04):前後端整合_作業一帶著做之打造後端 API:Part1_13':15"
流程:
a. 引入連線還有 header('Content-type: application/json;charset=utf-8');
b. 錯誤處理,檢查 $_GET[]
有沒有拿到東西;在這裡我們拿的資料是 site_key
c. 我們現在用的是 GET 方法拿到 site_key
d. sql 拿資料:要 nickname, content, created_at(記得一定要用防 sql injection 的方法 stmt prepare)
e. 錯誤處理:如果沒有結果的話,就回傳錯誤訊息
f. 為什麼要用get_result():
當使用 stmt prepare 且需要得到回傳的結果時,就要用這個函式
mysqli_stmt::get_result:
Gets a result set from a prepared statement as a mysqli_result object
g. 為什麼要用 array_push():
抓到資料以後,要把資料放到 array 裡面,用法:
<?php
$stack = array("orange", "banana");
array_push($stack, "apple", "raspberry");
print_r($stack);
?>
// 上面會輸出
Array
(
[0] => orange
[1] => banana
[2] => apple
[3] => raspberry
)
遇到的困難:
永遠檢查 sql 語法,方法就是把它丟進 mysql 裡面檢查
array 裡面永遠要用逗號分隔
程式碼:
<?php
require_once('conn.php');
header('Content-type: application/json;charset=utf-8');
if (
empty($_GET['site_key'])
) {
$json = array(
"ok" => false,
"message" => "Please add site_key in url"
);
$response = json_encode($json);
echo $response;
die();
}
$site_key = $_GET['site_key'];
$sql = "select nickname, content, created_at from discussions where site_key = ? order by id desc";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $site_key);
$result = $stmt->execute();
if (!$result) {
$json = array(
"ok" => false,
"message" => $conn->error
);
$response = json_encode($json);
echo $response;
die();
}
$result = $stmt->get_result();
$discussions = array();
while($row = $result->fetch_assoc()) {
array_push($discussions, array(
"nickname" => $row["nickname"],
"content" => $row["content"],
"created_at" => $row["created_at"]
));
}
$json = array(
"ok" => true,
"discussions" => $discussions
);
$response = json_encode($json);
echo $response;
?>
3. hw1_實作 API 串接
MTR05_第十二週(06/28 ~ 07/04):前後端整合_作業一帶著做之打造後端 API:Part2
a. 先用 bootstrap 刻 UI: 就是去找適合的物件貼上
b. 串 API 04':50"
b.1 先顯示留言資料:
一定開始要用 $(document).ready()
<script>
function escape(toOutput){
return toOutput.replace(/\&/g, '&')
.replace(/\</g, '<')
.replace(/\>/g, '>')
.replace(/\"/g, '"')
.replace(/\'/g, ''')
.replace(/\//g, '/');
}
$(document).ready(() => {
$.ajax({
url: "http://localhost:8080/christy/discussions/api_comments.php?site_key=christy",
}).done(function(data) {
if (!data.ok) {
alert(data.message)
return
}
const comments = data.discussions;
for (let comment of comments) {
$('.comments').append(`
<div class="card mt-3">
<div class="card-body">
<h5 class="card-title">${escape(comment.nickname)}</h5>
<p class="card-text">${escape(comment.content)}</p>
</div>
</div>
`)
}
});
})
</script>
b.2 新增留言:
先監聽表單送出事件,可以查 You might not need jQuery 要怎麼 POST
遇到的困難:
chrome 的 dev tool,如果把 selected context only 打勾,就不會顯示錯誤訊息了
因為非同源政策,所以要加一個 header 在自己寫的 API 檔案裡面
header('Access-Control-Allow-Origin: *');
因為要用 jQuery,所以要引入在 head 標籤裡;當然要記得引入 bootstrap
就算跟著老師一起做,還是會有打錯的地方,如果錯了,記得一定一定要停下來訂正,不要繼續跟著走,不然碼越多就越找不到
這次的錯誤是在用 POST 的時候,裡面的data: newCommentData,前面的 data 忘記打。
雖然影片裡面老師說,ES6 參數一樣就不用打,但是這裡參數不一樣!
天阿,找到錯誤好感動!
$.ajax({
type: 'POST',
url: 'http://localhost:8080/christy/discussions/api_add_comments.php',
data: newCommentData
}).done(function(data) {
if (!data.ok) {
alert(data.message)
return
}
4. hw1_實作API「載入更多」
MTR05_第十二週(06/28 ~ 07/04):前後端整合_作業一參考範例(請寫完作業再看)
流程:
有載入更多的按鈕,按下去以後會顯示多五筆留言。
留言順序由新到舊排列,留言大於五筆,才會出現載入更多的按鈕,按下去就會顯示多五筆留言;沒有更多留言時,就不會有載入更多的按鈕。
- 先去拿 before 這個資料,把 sql 分成兩種情況:
a. 網址參數有 before
b. 網址參數沒有 before
- 記得要帶 id
小結:API 就寫成兩種情況,如果在 postman 可以跑就差不多了
- 分頁功能有兩種,page-based, cursor-based
page-based 就是有分頁按鈕形式,可以任意跳到某一頁,每一頁的留言筆數是固定的那種
cursor-based 的重點在於 before and after
如果 API URL 帶的參數為:...?before=6
,就會顯示留言筆數 5, 4, 3, 2, 1
參數為:...?after=5
,就會顯示留言筆數為 6, 7, 8, 9, 10
- 04':00" - 11':50" 實作 api 載入更多
a. 根據 before 是不是空的,決定要帶什麼參數
我覺得重點觀念是有 before 跟 after 這兩個東西,難理解的觀念是 before 是哪裡來的?sql 語法怎麼寫?在網址上帶參數時,要怎麼規範?
無法再看第三次的時候理解,但是先繼續下去。
遇到的問題:
- 在 postman 檢查的時候,要注意 URL 的路徑
- 老師的程式碼,但是沒有防 sql injection,我下面有改寫。
<?php
require_once('conn.php');
header('Content-type: application/json;charset=utf-8');
header('Access-Control-Allow-Origin: *');
if (
empty($_GET['site_key'])
) {
$json = array(
"ok" => false,
"message" => "Please add site_key in url"
);
$response = json_encode($json);
echo $response;
die();
}
$site_key = $_GET['site_key'];
$sql =
"select id, nickname, content, created_at from discussions where site_key = ? " .
(empty($_GET['before']) ? "" : "and id < ? ") .
"order by created_at desc limit 5";
$stmt = $conn->prepare($sql);
if (empty($_GET['before'])) {
$stmt->bind_param('s', $site_key);
} else {
$stmt->bind_param('si', $site_key, $_GET['before']);
}
$result = $stmt->execute();
if (!$result) {
$json = array(
"ok" => false,
"message" => $conn->error
);
$response = json_encode($json);
echo $response;
die();
}
$result = $stmt->get_result();
$discussions = array();
while($row = $result->fetch_assoc()) {
array_push($discussions, array(
"id" => $row["id"],
"nickname" => $row["nickname"],
"content" => $row["content"],
"created_at" => $row["created_at"]
));
}
$json = array(
"ok" => true,
"discussions" => $discussions
);
$response = json_encode($json);
echo $response;
?>
- 我的程式碼,有防 sql injection
<?php
require_once('conn.php');
header('Content-type: application/json;charset=utf-8');
header('Access-Control-Allow-Origin: *');
if (
empty($_GET['site_key'])
) {
$json = array(
'ok' => false,
'message' => 'Please add site_key in url'
);
$response = json_encode($json);
echo $response;
die();
}
$site_key = $_GET['site_key'];
$before = $_GET['before'];
if (!$before) {
$sql = 'select id, nickname, content, created_at from discussions where site_key = ? order by id desc limit 5';
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $site_key);
} else {
$sql = 'select id, nickname, content, created_at from discussions where site_key = ? and id < ? order by id desc limit 5';
$stmt = $conn->prepare($sql);
$stmt->bind_param('si', $site_key, $before);
}
$result = $stmt->execute();
if (!$result) {
$json = array(
'ok' => false,
'message' => $conn->error
);
$response = json_encode($json);
echo $response;
die();
}
$result = $stmt->get_result();
$discussions = array();
while($row = $result->fetch_assoc()) {
array_push($discussions, array(
'id' => $row['id'],
'nickname' => $row['nickname'],
'content' => $row['content'],
'created_at' => $row['created_at']
));
}
$json = array(
'ok' => true,
'discussions' => $discussions
);
$response = json_encode($json);
echo $response;
?>
5. hw1_實作留言板「載入更多」功能
MTR05_第十二週(06/28 ~ 07/04):前後端整合_作業一參考範例(請寫完作業再看)12':00" 開始
流程:
把顯示留言包成一個函式
16':13" 實作載入更多的按鈕
a. 「載入更多」按鈕要放在 comments 裡面,可以把它獨立成一個字串
b. .on()
:jQuery 的 addeventlistener
c. 18':17" 先把載入更多的按鈕移除,加上新的留言,再把按鈕加回去
用事件代理的方式
遇到的問題:
更改檔名之後,要特別注意 url 路徑
Id 不用 escape() 因為我們跳脫的是特殊符號,數字不需要
老實說看完兩遍影片並跟著實作以後,並沒有很懂裡面的一些細節。
為什麼會有錯誤訊息:
Access to XMLHttpRequest at 'file:///Users/christy/.bitnami/stackman/machines/xampp/volumes/root/htdocs/christy/p_discussions/index.html' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
是因為我把 url 的名稱改了,但是 ajax 裡面如果名稱有變,應該要完整的把名字寫出來,如果只寫成 url,
,就會發生這個錯誤。
要寫完整變成 url: getCommentsURL,
後面接變數名稱
要怎麼在點擊按鈕時,除了抓留言以外,去偵測留言的數量?
為什麼在 index.html 裡面,getCommentsAPI 這個函式要放一個 call back fn 當第三個參數?
是為了確保執行順序嗎?例如說一定要先確認是否拿到 siteKey and before 才能繼續下去?這裡不是很明白
function getCommentsAPI(siteKey, before, cb) {
let url = `http://localhost:8080/christy/p_discussions/api_comments.php?site_key=${siteKey}`
if (before) {
url += '&before=' + before
}
$.ajax({
url,
}).done(function(data) {
cb(data)
});
}
- 如果看完影片自己硬做的話,就會變成網路上看到的文章先在資料庫新增一個表格存 pageToken,接著把全部的 api 都改掉,然後可能會在哪個坑跌倒,又可能就沒有然後了。
所以說我應該要好好利用資源問問題,不要再亂來了。