[Series Thực Chiến E-commerce] Bài 32: "Bắt Bug" Copy-Paste - API Cập nhật Bài Viết (Update Blog)
Chào bố đời! Tốc độ lên bài của chúng ta dạo này đúng là thần tốc. Chuẩn bị mang series này lên trang chủ Viblo là vừa đẹp rồi đấy!
Hôm nay, chúng ta bước sang tính năng Sửa bài viết (Update Blog). Viết content dài thì kiểu gì cũng có lúc sai lỗi chính tả, hoặc sau 1 năm cần cập nhật lại thông tin cho mới mẻ. Nhu cầu Update là bắt buộc phải có.
Tuy nhiên, đoạn code bố đời vừa quăng lên chứa đến 3 "hạt sạn" siêu kinh điển của hội anh em Dev khi dùng tổ hợp phím Ctrl + C / Ctrl + V. Khi viết blog chia sẻ kỹ thuật, việc chỉ ra những lỗi sai thực tế thế này lại càng làm bài viết thêm giá trị. Cùng mình bóc phốt chính đoạn code này nhé!
1. Phẫu thuật Controller: 2 Hạt sạn chí mạng
Anh em nhìn lại đoạn Controller gốc:
// Cú lừa 1: Đang update mà lại ném ra 'createdBlog'
return res.json({
success: response ? true : false,
createdBlog: response ? response : 'Cannot update blog'
});
Và quan trọng nhất: Đâu rồi cái thuật toán Update Slug? Giống y hệt Bài 16 (Update Product), nếu Admin sửa lại Tiêu đề (title) mà Backend không tự động sinh lại đường dẫn (slug), thì tiêu đề một đằng, link URL một nẻo, SEO rớt thảm hại!
Anh em sửa lại file controllers/blog.js cho chuẩn thực chiến thế này nhé:
const slugify = require('slugify'); // Đừng quên gọi vũ khí SEO này ra
// Cập nhật blog
const updateBlog = asyncHandler(async (req, res) => {
// Lấy ID bài viết từ URL
const { bid } = req.params;
// Validate: Chặn mấy cú call API gửi body rỗng tuếch
if (Object.keys(req.body).length === 0) throw new Error('Missing inputs - Không có dữ liệu để cập nhật');
// 💡 FIX BUG 1: Xử lý vụ đổi tên Bài viết -> Tự động đổi Slug
if (req.body && req.body.title) {
req.body.slug = slugify(req.body.title);
}
// Tiến hành Update
const response = await Blog.findByIdAndUpdate(bid, req.body, { new: true });
// 💡 FIX BUG 2: Đổi tên biến trả về cho chuẩn ngữ nghĩa
return res.json({
success: response ? true : false,
updatedBlog: response ? response : 'Cannot update blog - Cập nhật thất bại'
});
});
module.exports = {
createBlog,
updateBlog, // Xuất xưởng
};
2. Gỡ mìn ở Router: Râu ông nọ cắm cằm bà kia
Anh em soi kỹ lại đoạn code Router lúc nãy:
router.put('/blogs/:id', [verifyAccessToken, isAdmin], ctrls.updateBlog);
Khúc này khai báo biến động là :id. Tức là req.params nó sẽ sinh ra một object { id: "..." }.
Thế nhưng ở Controller, anh em lại đi bốc const { bid } = req.params;. Biến bid lúc này sẽ là undefined, Mongoose cầm chữ undefined đi query thì nó quăng lỗi vỡ mặt ngay!
Sự đồng nhất dữ liệu giữa Router và Controller là cực kỳ quan trọng. Anh em mở file routers/blog.js và chỉnh lại một chút xíu thôi:
const router = require('express').Router();
const ctrls = require('../controllers/blog');
const { verifyAccessToken, isAdmin } = require('../middlewares/verifyToken');
router.post('/blogs', [verifyAccessToken, isAdmin], ctrls.createBlog);
// 💡 FIX BUG 3: Đổi ':id' thành ':bid' để khớp với biến nhận ở Controller
router.put('/blogs/:bid', [verifyAccessToken, isAdmin], ctrls.updateBlog);
module.exports = router;
Lời kết
Test trên Postman: Bố đời kẹp Token Admin vào, bắn PUT tới http://localhost:5000/api/blog/blogs/<id-bài-viết>, sửa thử cái title xem slug có nhảy theo không. Nhảy mượt mà là done task!
Vậy là đăng bài được rồi, sửa bài được rồi. Việc tiếp theo là đem các bài viết này ra trưng bày trên giao diện trang chủ Blog để độc giả vào đọc.
Đó cũng chính là nội dung của bài tiếp theo: Lession 33: Get All Blogs. Ở bài này, liệu chúng ta có áp dụng lại công thức Filter, Sort, Pagination kinh điển của Product sang cho Blog không?
All rights reserved