🎯 1. Mục tiêu bài học
Ở các bài trước, chúng ta đã học:
Bài 05: Promise & Async/Await.
Bài 06: Fetch API.
Bài 07: Xử lý JSON & HTTP.
Trong bài 08, chúng ta sẽ kết hợp tất cả kiến thức trên để xây dựng một ứng dụng JavaScript giao tiếp trực tiếp với Laravel REST API.
Sau bài này, bạn có thể:
Gọi API Laravel bằng JavaScript.
Lấy dữ liệu từ Laravel và hiển thị lên giao diện.
Gửi dữ liệu bằng phương thức POST.
Cập nhật dữ liệu bằng PUT/PATCH.
Xóa dữ liệu bằng DELETE.
Xử lý lỗi HTTP và JSON.
Xây dựng một module JavaScript chuyên dùng để gọi API.
2. Mô hình JavaScript giao tiếp Laravel API
Trong kiến trúc ứng dụng hiện đại, JavaScript không truy vấn trực tiếp database.
Thay vào đó, JavaScript gửi HTTP Request đến Laravel.
Mô hình hoạt động:
┌──────────────────────────┐
│ FRONTEND │
│ │
│ HTML + CSS + JavaScript│
│ │
└────────────┬─────────────┘
│
│ HTTP Request
│ GET / POST / PUT / DELETE
▼
┌──────────────────────────┐
│ LARAVEL 13 │
│ │
│ routes/api.php │
│ │ │
│ Controller │
│ │ │
│ Model │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ DATABASE │
│ │
│ MySQL │
└──────────────────────────┘Ví dụ:
JavaScript muốn lấy danh sách bài viết.
Nó gửi:
GET /api/postsLaravel nhận request, truy vấn database và trả về JSON.
[
{
"id": 1,
"title": "Học Laravel 13"
},
{
"id": 2,
"title": "Học JavaScript"
}
]JavaScript nhận JSON và hiển thị lên HTML.
3. Chuẩn bị Laravel REST API
Giả sử chúng ta đã có project Laravel 13.
3.1. Khai báo API Route
Mở file:
routes/api.phpKhai báo:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\PostController;
Route::get('/posts', [PostController::class, 'index']);
Route::post('/posts', [PostController::class, 'store']);
Route::get('/posts/{id}', [PostController::class, 'show']);
Route::put('/posts/{id}', [PostController::class, 'update']);
Route::delete('/posts/{id}', [PostController::class, 'destroy']);Các endpoint của chúng ta:
HTTP Method | Endpoint | Chức năng |
|---|---|---|
GET |
| Lấy danh sách |
GET |
| Xem chi tiết |
POST |
| Thêm bài viết |
PUT |
| Cập nhật |
DELETE |
| Xóa |
3.2. Tạo PostController
Chạy lệnh:
php artisan make:controller Api/PostControllerMở file:
app/Http/Controllers/Api/PostController.phpCode:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
// Lấy danh sách
public function index()
{
return response()->json(
Post::latest()->get()
);
}
// Thêm bài viết
public function store(Request $request)
{
$data = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);
$post = Post::create($data);
return response()->json($post, 201);
}
// Chi tiết
public function show($id)
{
return response()->json(
Post::findOrFail($id)
);
}
// Cập nhật
public function update(Request $request, $id)
{
$post = Post::findOrFail($id);
$data = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);
$post->update($data);
return response()->json($post);
}
// Xóa
public function destroy($id)
{
$post = Post::findOrFail($id);
$post->delete();
return response()->json([
'message' => 'Deleted successfully'
]);
}
}Lưu ý: Model Post cần cho phép gán dữ liệu tương ứng thông qua $fillable, ví dụ:
protected $fillable = [
'title',
'content',
];Kiểm tra API:
php artisan route:list --path=api4. JavaScript gọi GET API
Bây giờ chúng ta tạo giao diện HTML.
File index.html:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>JavaScript Laravel API</title>
</head>
<body>
<h2>Danh sách bài viết</h2>
<button onclick="loadPosts()">
Tải bài viết
</button>
<div id="posts"></div>
<script src="app.js"></script>
</body>
</html>File app.js:
async function loadPosts() {
try {
const response = await fetch(
'http://localhost:8000/api/posts'
);
if (!response.ok) {
throw new Error('Không thể tải dữ liệu');
}
const posts = await response.json();
const container = document.getElementById('posts');
container.innerHTML = posts.map(post => `
<div>
<h3>${escapeHTML(post.title)}</h3>
<p>${escapeHTML(post.content)}</p>
</div>
`).join('');
} catch (error) {
console.error(error);
}
}
function escapeHTML(value) {
return String(value ?? '').replace(/[&<>"']/g, char => ({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
})[char]);
}Giải thích:
fetch(): Gửi HTTP Request.await: Chờ Laravel trả kết quả.response.ok: Kiểm tra HTTP Status.response.json(): Chuyển JSON thành JavaScript Object.map(): Duyệt danh sách bài viết.innerHTML: Hiển thị nội dung lên HTML.
Ở đây, chúng ta dùng escapeHTML() để tránh đưa trực tiếp nội dung không đáng tin cậy vào HTML.
5. JavaScript gửi POST API
Bây giờ chúng ta thêm chức năng tạo bài viết.
HTML:
<h2>Thêm bài viết</h2>
<form id="postForm">
<input
type="text"
id="title"
placeholder="Tiêu đề"
required
>
<br><br>
<textarea
id="content"
placeholder="Nội dung"
required
></textarea>
<br><br>
<button type="submit">
Thêm bài viết
</button>
</form>JavaScript:
document.getElementById('postForm')
.addEventListener('submit', async function(event) {
event.preventDefault();
const data = {
title: document.getElementById('title').value,
content: document.getElementById('content').value
};
try {
const response = await fetch(
'http://localhost:8000/api/posts',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data)
}
);
const result = await response.json();
if (!response.ok) {
throw new Error(
result.message || 'Thêm thất bại'
);
}
alert('Thêm bài viết thành công!');
this.reset();
loadPosts();
} catch (error) {
alert(error.message);
}
});Điểm quan trọng:
method: 'POST'Khai báo phương thức gửi dữ liệu.
'Content-Type': 'application/json'Thông báo với Laravel rằng dữ liệu gửi lên có định dạng JSON.
body: JSON.stringify(data)Chuyển JavaScript Object thành chuỗi JSON.
Ví dụ dữ liệu gửi đi:
{
"title": "Học JavaScript",
"content": "JavaScript gọi Laravel API"
}6. JavaScript cập nhật PUT API
Ví dụ muốn cập nhật bài viết có ID = 1.
async function updatePost(id, data) {
try {
const response = await fetch(
`http://localhost:8000/api/posts/${id}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data)
}
);
const result = await response.json();
if (!response.ok) {
throw new Error(result.message || 'Cập nhật thất bại');
}
console.log(result);
alert('Cập nhật thành công!');
loadPosts();
} catch (error) {
console.error(error);
}
}Gọi hàm:
updatePost(1, {
title: 'Laravel 13 nâng cao',
content: 'Nội dung mới'
});Laravel nhận request:
PUT /api/posts/1Sau đó cập nhật dữ liệu trong database.
7. JavaScript xóa DELETE API
Tạo hàm:
async function deletePost(id) {
if (!confirm('Bạn có chắc muốn xóa?')) {
return;
}
try {
const response = await fetch(
`http://localhost:8000/api/posts/${id}`,
{
method: 'DELETE',
headers: {
'Accept': 'application/json'
}
}
);
const result = await response.json();
if (!response.ok) {
throw new Error(result.message || 'Xóa thất bại');
}
alert('Xóa thành công!');
loadPosts();
} catch (error) {
console.error(error);
}
}Gọi:
deletePost(1);Laravel thực hiện:
$post = Post::findOrFail($id);
$post->delete();8. Tổng hợp 4 phương thức REST API
Đây là kiến thức rất quan trọng khi làm việc với Laravel API.
Phương thức | Chức năng | JavaScript |
|---|---|---|
GET | Đọc dữ liệu | fetch() |
POST | Thêm dữ liệu | fetch() |
PUT | Cập nhật toàn bộ | fetch() |
PATCH | Cập nhật một phần | fetch() |
DELETE | Xóa dữ liệu | fetch() |
Ví dụ mô hình CRUD:
CRUD với JavaScript và Laravel
READ
GET /api/posts
CREATE
POST /api/posts
UPDATE
PUT /api/posts/1
DELETE
DELETE /api/posts/1
9. Xây dựng API Service chuyên nghiệp
Trong ứng dụng thực tế, chúng ta không nên viết fetch() lặp đi lặp lại ở nhiều nơi.
Thay vào đó, tạo một module chuyên xử lý API.
Cấu trúc thư mục:
project/
│
├── index.html
│
└── js/
├── app.js
├── api.js
└── posts.js9.1. File api.js
const API_URL = 'http://localhost:8000/api';
async function apiRequest(endpoint, options = {}) {
const response = await fetch(
`${API_URL}${endpoint}`,
{
...options,
headers: {
'Accept': 'application/json',
...options.headers
}
}
);
const data = await response.json();
if (!response.ok) {
throw new Error(
data.message || 'API Request Failed'
);
}
return data;
}9.2. File posts.js
const Posts = {
getAll() {
return apiRequest('/posts');
},
getById(id) {
return apiRequest(`/posts/${id}`);
},
create(data) {
return apiRequest('/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
},
update(id, data) {
return apiRequest(`/posts/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
},
delete(id) {
return apiRequest(`/posts/${id}`, {
method: 'DELETE'
});
}
};9.3. File app.js
async function init() {
try {
const posts = await Posts.getAll();
console.log(posts);
} catch (error) {
console.error(error.message);
}
}
init();Như vậy, khi cần lấy bài viết, chúng ta chỉ cần:
const posts = await Posts.getAll();Khi thêm:
await Posts.create({
title: 'Bài viết mới',
content: 'Nội dung mới'
});Khi cập nhật:
await Posts.update(1, {
title: 'Tiêu đề mới',
content: 'Nội dung mới'
});Khi xóa:
await Posts.delete(1);Đây chính là cách tổ chức JavaScript theo hướng API Service, một nền tảng quan trọng trước khi chuyển sang Vue và React.
10. Một số lỗi thường gặp khi JavaScript gọi Laravel API
Lỗi | Nguyên nhân | Cách xử lý |
|---|---|---|
404 | Sai API URL hoặc route | Kiểm tra |
401 | Chưa xác thực | Kiểm tra token/session |
403 | Không có quyền | Kiểm tra middleware |
422 | Validation thất bại | Kiểm tra dữ liệu gửi lên |
500 | Lỗi server | Kiểm tra Laravel Log |
CORS | Khác origin chưa được cho phép | Cấu hình CORS |
Network Error | Không kết nối được server | Kiểm tra Laravel đang chạy |
Lưu ý về CORS: Nếu frontend và Laravel chạy ở hai origin khác nhau, Laravel phải cho phép origin của frontend. Không nên tùy tiện mở quyền truy cập cho mọi origin trong môi trường production.
Nếu sử dụng Laravel Sanctum với SPA, chúng ta còn cần cấu hình cookie, CSRF và credentials phù hợp. Nội dung này sẽ được thực hành ở Bài 28.
11. Bài tập thực hành
Xây dựng ứng dụng quản lý bài viết bằng JavaScript và Laravel REST API.
Yêu cầu:
Bài tập nâng cao:
Tạo thêm chức năng tìm kiếm bài viết.
Ví dụ:
GET /api/posts?search=LaravelLaravel xử lý:
public function index(Request $request)
{
$query = Post::query();
if ($request->filled('search')) {
$query->where(
'title',
'like',
'%' . $request->search . '%'
);
}
return response()->json(
$query->latest()->get()
);
}JavaScript gọi:
const posts = await apiRequest(
'/posts?search=Laravel'
);12. Tổng kết Bài 08
Sau 8 bài đầu tiên, chúng ta đã hoàn thành nền tảng JavaScript hiện đại và cách giao tiếp với Laravel REST API.
🎓 Hoàn thành PHẦN 1
- JavaScript hiện đại
- ES6+
- Array & Object
- Module & Import / Export
- Promise & Async/Await
- Fetch API
- Xử lý JSON & HTTP
- JavaScript gọi Laravel REST API
🚀 Bài tiếp theo: BÀI 09 — VUE LÀ GÌ?
Chúng ta sẽ bắt đầu tìm hiểu Vue.js:
Vue.js là gì?
Tại sao cần Vue khi đã có JavaScript?
Vue giải quyết những vấn đề nào?
Vue hoạt động như thế nào?
Vue khác gì với jQuery và JavaScript thuần?
Khi nào nên sử dụng Vue trong ứng dụng Laravel?
Mục tiêu là hiểu bản chất Vue trước khi cài đặt và lập trình ứng dụng thực tế ở Bài 10.
✨ Made by AI · 📘 Lớp học công nghệ hiện đại ✨




Không có nhận xét nào:
Đăng nhận xét