NTM Solutions

Bài đăng nổi bật

🚀 Laravel 12 (2026) — Từ PHP Core đến Full Stack📘

Nếu cập nhật theo Laravel 12 LTS (2026) thì mình sẽ chia thành các phần như sau để người học đi từ PHP Core → Laravel → Triển khai dự án th...

Chủ Nhật, 1 tháng 11, 2026

📘 BÀI 08 — JAVASCRIPT GỌI LARAVEL REST API

🎯 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ể:

  1. Gọi API Laravel bằng JavaScript.

  2. Lấy dữ liệu từ Laravel và hiển thị lên giao diện.

  3. Gửi dữ liệu bằng phương thức POST.

  4. Cập nhật dữ liệu bằng PUT/PATCH.

  5. Xóa dữ liệu bằng DELETE.

  6. Xử lý lỗi HTTP và JSON.

  7. 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/posts

Laravel 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.php

Khai 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

/api/posts

Lấy danh sách

GET

/api/posts/1

Xem chi tiết

POST

/api/posts

Thêm bài viết

PUT

/api/posts/1

Cập nhật

DELETE

/api/posts/1

Xóa

3.2. Tạo PostController

Chạy lệnh:

php artisan make:controller Api/PostController

Mở file:

app/Http/Controllers/Api/PostController.php

Code:

<?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=api

4. 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 => ({
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    })[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/1

Sau đó 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.js

9.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 route:list

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

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=Laravel

Laravel 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

  1. JavaScript hiện đại
  2. ES6+
  3. Array & Object
  4. Module & Import / Export
  5. Promise & Async/Await
  6. Fetch API
  7. Xử lý JSON & HTTP
  8. JavaScript gọi Laravel REST API
HOÀN THÀNH 8/8 BÀI

🚀 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

Facebook Youtube RSS