本文為 Lidemy [BE201] 裡面的影片,[超重要觀念:Middleware] 之 [再做一個超簡易留言板,只要有新增就好] 到 [把留言板變得更完整] 之 [實作編輯功能] 的實作過程,主要以 express 練習做一個有新增會員、登入、留言、編輯及刪除功能的留言板。
零、內容摘要
1. 新增留言流程:開 table → views 做首頁畫面的留言輸入框 → index.js 新增路由 → controllers → 先把 models 寫好再回頭寫 controllers → controllers → views
2. What I have learned for now 到目前為止的概念有:
a. 大致流程就是:
table → routes → the methods in controllers → models → controllers → views
b. 其實也沒有什麼所謂固定的流程吧,但基本上就是「做了這個才能做下一步」,這樣做比較順暢而已。
c. 剛在思考關於畫面,什麼時候可以拿到畫面或者何時該做畫面,畢竟畫面對我很重要,是一種視覺上的輔助,但是後端似乎著重在「資料」,是另一種思考模式
一、實作留言板新增功能
1. 開 table:
id
username in 32 length wiith varchar
content with Text
2. 新增路由
// index.js
const commentController = require('./controllers/comment')
app.get('/', commentController.index)
app.post('/comments', commentController.add)
3. controllers > comment.js
// controllers > comment.js
const commentModel = require('../models/comment')
const commentController = {
add: (req, res) => {
}
}
module.exports = commentController
4. models > comment.js
// models > comment.js
const db = require('../db')
const commentModel = {
add: (username, content, cb) => {
db.query(
'insert into comments(username, content) values(?, ?)',
[username, content],
(err, results) => {
if (err) return cb(err)
cb(null)
}
);
},
// 讀取的等一下再寫
get: (username, cb) => {
// db.query(
// 'SELECT * from users where username = ?', [username],
// (err, results) => {
// if (err) return cb(err)
// cb(null, results[0])
// }
// );
}
}
module.exports = commentModel
5. controllers > comment.js
裡面的 console.log()
是拿來 debug 用的
// controllers > comment.js
const commentModel = require('../models/comment')
const commentController = {
add: (req, res) => {
const { username } = req.session
const { content } = req.body
if (!username || !content) {
console.log('err')
return res.redirect('/')
}
commentModel.add(username, content, (err) => {
console.log('err1', err)
return res.redirect('/')
})
}
}
module.exports = commentController
6. 讀取留言
a. 來複習 sql query 吧
可以先在軟體裡面的 query 跑跑看:
// models > comment.js
getAll: (cb) => {
db.query(
`SELECT U.nickname, C.content
FROM comments as C
LEFT JOIN users as U on U.username = C.username
ORDER BY createdAt DESC
`,
(err, results) => {
if (err) return cb(err)
cb(null, results)
}
);
}
b. controllers 裡面新增一個 index 當作 method
// controllers > comment.js
index: (req, res) => {
commentModel.getAll((err, results) => {
if (err) {
console.log(err)
}
res.render('index', {
comments: results
})
})
}
c. views > index.ejs
<% comments.forEach(function(comment) { %>
<div>
<h2><%= comment.nickname %></h2>
<p><%= comment.content %></p>
</div>
<% }) %>
二、認真規劃一個留言板吧
1. 思考全貌
a. 刪除留言:利用 GET 方式,按下刪除按鈕,先把某一則留言刪掉,再導回首頁
GET /delete_comments/id → /
b. 編輯留言:按下編輯按鈕時,導到另一個編輯頁面;編輯完後按下 submit 回到首頁
GET /update_comments/id → form POST /update_comments/id → /
2. 規劃結構
開 table,通常會有:
id
username
content
createdAt
updatedAt
註:
a. createdAt:type → datetime; default → current_timestamp()
b. updatedAt 的時間搞不定,查到的資料應該是下面的設定,但是 sequel pro 一直報錯不給我改
updatedAt:type → datetime; default → current_timestamp()?; extra → on update CURRENT_TIMESTAMP
3. 實作刪除功能
a. comment.ejs 加上刪除按鈕:如果不是使用者的留言,就沒有刪除按鈕
<% if (username === comment.username) { %>
<a href="delete_comments/<%= comment.id %>">delete</a>
<% } %>
b. 加上路由
app.get('/delete_comments/:id', commentController.delete)
註:記得 getAll 的 controller 裡面要加上 SELECT U.nickname, C.content, C.id, C.username
要拿到 id & username 才可以
c. controllers
delete: (req, res) => {
commentModel.delete(req.session.username, req.params.id, err => {
res.redirect('/')
})
}
d. Models
delete: (username, id, cb) => {
db.query(
`DELETE FROM comments where id = ? AND username = ?`, [id, username],
(err) => {
if (err) return cb(err)
cb(null)
}
);
}
4. 實作編輯功能
a. 首頁畫面,複製刪除的程式碼改成編輯,並且新增一個編輯頁面如下
註:少了一個等號,送出編輯後的內容抓不到
<h1>Edit Page</h1>
<form method="POST" action="/update_comments/<%= comment.id %>">
<textarea name="content" id="" cols="30" rows="10"><%= comment.content %></textarea>
<input type="submit">
</form>
b. 路由
app.get('/update_comments/:id', commentController.update)
app.post('/update_comments/:id', commentController.handleUpdate)
c. controllers 先寫個大概 update & handleUpdate
d. models 新增函式 get & delete
get: (id, cb) => {
db.query(
`SELECT U.nickname, C.content, C.id, C.username
FROM comments as C
LEFT JOIN users as U on U.username = C.username
WHERE C.id = ?
`, [id],
(err, results) => {
if (err) return cb(err)
cb(null, results[0] || {})
}
);
},
update: (username, id, content, cb) => {
db.query(
`UPDATE comments SET content = ? WHERE id = ? AND username = ?`,
[content, id, username],
(err) => {
if (err) return cb(err)
cb(null)
}
);
}
e. controllers
update: (req, res) => {
commentModel.get(req.params.id, (err, result) => {
res.render('update', {
comment: result
})
})
},
handleUpdate: (req, res) => {
commentModel.update(req.session.username, req.params.id, req.body.content, err => {
res.redirect('/')
})
}