REST API là cầu nối để Laravel giao tiếp với Website, JavaScript, Mobile App hoặc các hệ thống khác thông qua HTTP và dữ liệu JSON.
Ở phần trước, chúng ta đã hoàn thành Logging & Debug.
Từ bài này, chúng ta bước sang:
🌐 PHẦN 9 — REST API
Gồm:
Bài 41 — REST API
Bài 42 — API Resource
Bài 43 — Sanctum
Bài 44 — API Authentication
Mục tiêu của phần này là biến Laravel từ một Website thông thường thành một Backend API có thể cung cấp dữ liệu cho nhiều loại ứng dụng khác nhau.
1. REST API là gì?
Khi xây dựng một Website Laravel truyền thống:
Browser
↓
Laravel
↓
Blade
↓
HTML
Laravel xử lý request rồi trả về HTML để trình duyệt hiển thị.
Ví dụ:
GET /blog
Laravel trả về:
<html>
...
</html>
Nhưng với API, cách hoạt động sẽ khác:
Website
Mobile App
JavaScript
React
Vue
Next.js
↓
REST API
↓
Laravel
↓
Database
Laravel không nhất thiết trả về HTML.
Thay vào đó, Laravel trả về:
{
"id": 1,
"title": "Laravel 13 là gì?"
}
Đây chính là nền tảng của API.
2. API là gì?
API là viết tắt của:
Application Programming Interface
Có thể hiểu đơn giản:
API là một "cổng giao tiếp" cho phép các chương trình trao đổi dữ liệu với nhau.
Ví dụ Blog CMS của chúng ta có bài viết:
ID: 1
Title: Laravel 13 là gì?
Category: Laravel
Website có thể lấy dữ liệu bằng:
GET /api/posts
Laravel trả về:
[
{
"id": 1,
"title": "Laravel 13 là gì?"
},
{
"id": 2,
"title": "Routing trong Laravel 13"
}
]
Một ứng dụng mobile có thể gọi chính API đó.
Một ứng dụng React cũng có thể gọi.
Một ứng dụng Vue cũng có thể gọi.
Như vậy:
┌── Website
│
├── Mobile App
│
Laravel API ─────┼── React
│
├── Vue
│
└── Third-party App
Backend chỉ cần cung cấp API.
3. REST là gì?
REST là viết tắt của:
Representational State Transfer
REST không phải là một thư viện.
REST là một phong cách thiết kế API dựa trên HTTP.
Ví dụ chúng ta có đối tượng:
Post
API có thể thiết kế:
GET /api/posts
GET /api/posts/1
POST /api/posts
PUT /api/posts/1
DELETE /api/posts/1
Nhìn vào URL và HTTP method, chúng ta có thể hiểu API đang làm gì.
4. CRUD và REST API
REST API rất phù hợp với CRUD.
| CRUD | HTTP | Endpoint |
|---|---|---|
| Create | POST | /api/posts |
| Read | GET | /api/posts |
| Read one | GET | /api/posts/1 |
| Update | PUT/PATCH | /api/posts/1 |
| Delete | DELETE | /api/posts/1 |
Có thể hình dung:
POSTS API
GET /api/posts
↓
Danh sách bài viết
GET /api/posts/1
↓
Chi tiết bài viết
POST /api/posts
↓
Tạo bài viết
PUT /api/posts/1
↓
Cập nhật bài viết
DELETE /api/posts/1
↓
Xóa bài viết
Đây là cấu trúc rất phổ biến khi thiết kế REST API.
5. HTTP Methods
REST API sử dụng các HTTP method chính.
GET
Dùng để lấy dữ liệu.
GET /api/posts
Ví dụ:
Lấy danh sách bài viết
POST
Dùng để tạo dữ liệu mới.
POST /api/posts
Ví dụ gửi:
{
"title": "Laravel 13 REST API",
"category_id": 1
}
PUT
Thường dùng để cập nhật toàn bộ resource.
PUT /api/posts/1
PATCH
Thường dùng để cập nhật một phần resource.
PATCH /api/posts/1
Ví dụ chỉ thay đổi:
{
"title": "Laravel 13 API"
}
DELETE
Dùng để xóa resource.
DELETE /api/posts/1
6. API trả về JSON
Một trong những điểm quan trọng nhất khi xây dựng API là dữ liệu thường được trao đổi dưới dạng JSON.
Ví dụ:
{
"id": 1,
"title": "Laravel 13",
"status": "published"
}
Laravel có thể trả về JSON rất đơn giản.
Ví dụ:
return response()->json([
'message' => 'Hello API'
]);
Kết quả:
{
"message": "Hello API"
}
Laravel cũng có thể tự chuyển array thành JSON response trong nhiều trường hợp.
7. Laravel 13 và API routes
Một điểm rất quan trọng đối với người học Laravel hiện nay:
Laravel không nhất thiết tạo sẵn routes/api.php trong một project mới.
API routing là phần có thể cài đặt thêm.
Trong Laravel, chúng ta có thể sử dụng:
php artisan install:api
Lệnh này dùng để cài đặt API routing và chuẩn bị cấu trúc cần thiết cho API. Laravel cũng sử dụng lệnh này trong quá trình thiết lập Sanctum ở các phiên bản hiện đại.
Sau khi chạy:
php artisan install:api
project sẽ có thêm:
routes/
├── web.php
├── console.php
└── api.php
8. web.php và api.php
Có thể hiểu đơn giản:
routes/web.php
Dành cho Website:
Browser
↓
web.php
↓
Controller
↓
Blade
↓
HTML
routes/api.php
Dành cho API:
Client
↓
api.php
↓
Controller
↓
JSON
API routes hướng tới các request stateless, khác với nhóm route web vốn có session, cookie và CSRF protection.
9. Tạo API route đầu tiên
Sau khi chạy:
php artisan install:api
mở:
routes/api.php
Thêm:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/hello', function () {
return response()->json([
'message' => 'Hello Laravel 13 API'
]);
});
Chạy Laravel:
php artisan serve
Sau đó truy cập:
http://127.0.0.1:8000/api/hello
Kết quả:
{
"message": "Hello Laravel 13 API"
}
Chúng ta vừa tạo API đầu tiên.
10. Vì sao có /api?
Khi route được khai báo trong API routing:
Route::get('/hello', ...);
URL API thường sẽ là:
/api/hello
Thay vì:
/hello
Do đó:
routes/api.php
có thể chứa:
Route::get('/posts', ...);
và client gọi:
GET /api/posts
11. API lấy danh sách Posts
Bây giờ chúng ta áp dụng vào Blog CMS.
Model:
app/Models/Post.php
Trong:
routes/api.php
có thể viết:
use App\Models\Post;
use Illuminate\Support\Facades\Route;
Route::get('/posts', function () {
return Post::all();
});
Truy cập:
GET /api/posts
Laravel có thể chuyển Eloquent model hoặc collection thành JSON response.
Ví dụ kết quả:
[
{
"id": 1,
"user_id": 1,
"category_id": 2,
"title": "Laravel 13 là gì?",
"slug": "laravel-13-la-gi",
"status": "published"
},
{
"id": 2,
"user_id": 1,
"category_id": 3,
"title": "Laravel Routing",
"slug": "laravel-routing",
"status": "published"
}
]
12. Nhưng không nên nhét quá nhiều logic vào route
Đoạn này:
Route::get('/posts', function () {
return Post::all();
});
chạy được.
Nhưng khi project lớn lên, chúng ta không nên đưa toàn bộ logic vào route.
Thay vào đó:
Route
↓
Controller
↓
Model
↓
Database
Đây cũng chính là cách chúng ta đã học ở những bài Controller và CRUD trước đó.
13. Tạo API Controller
Chạy:
php artisan make:controller Api/PostController
Laravel tạo:
app/
└── Http/
└── Controllers/
└── Api/
└── PostController.php
Mở file:
app/Http/Controllers/Api/PostController.php
Viết:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Post;
class PostController extends Controller
{
public function index()
{
return Post::all();
}
}
14. Kết nối Route với Controller
Mở:
routes/api.php
Viết:
<?php
use App\Http\Controllers\Api\PostController;
use Illuminate\Support\Facades\Route;
Route::get('/posts', [PostController::class, 'index']);
Bây giờ:
GET /api/posts
sẽ chạy:
PostController@index
Luồng hoạt động:
GET /api/posts
↓
routes/api.php
↓
PostController@index
↓
Post::all()
↓
Database
↓
JSON
15. API lấy một Post
Thêm vào Controller:
public function show(Post $post)
{
return $post;
}
Route:
Route::get('/posts/{post}', [PostController::class, 'show']);
Bây giờ:
GET /api/posts/1
Laravel sẽ tìm:
Post ID = 1
và trả về JSON.
Ví dụ:
{
"id": 1,
"title": "Laravel 13 là gì?",
"slug": "laravel-13-la-gi",
"status": "published"
}
Đây chính là Route Model Binding mà chúng ta đã học ở phần Routing.
16. API chỉ lấy bài Published
Trong Blog CMS, chúng ta không muốn API công khai trả về tất cả bài viết.
Ví dụ:
draft
hidden
scheduled
không nên xuất hiện trong API public.
Model Post của chúng ta đã có scope:
Post::published()
Do đó Controller có thể viết:
public function index()
{
return Post::published()
->with(['user', 'category'])
->latest('published_at')
->paginate(10);
}
Khi đó:
GET /api/posts
chỉ lấy những bài đã publish.
Đây chính là cách kết hợp:
Eloquent
+
Scope
+
Relationship
+
Pagination
+
REST API
17. API response có cấu trúc rõ ràng
Thay vì trả thẳng:
return Post::all();
chúng ta có thể tạo response:
return response()->json([
'success' => true,
'data' => Post::all()
]);
Kết quả:
{
"success": true,
"data": [
{
"id": 1,
"title": "Laravel 13 là gì?"
},
{
"id": 2,
"title": "Laravel Routing"
}
]
}
Cách này giúp client dễ xử lý response.
18. HTTP Status Code
API không chỉ trả dữ liệu.
API còn cần trả về HTTP status code phù hợp.
Một số status code quan trọng:
| Code | Ý nghĩa |
|---|---|
| 200 | OK |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 422 | Validation Error |
| 500 | Server Error |
Ví dụ lấy dữ liệu thành công:
return response()->json([
'data' => $posts
], 200);
19. API tạo Post
Ví dụ:
public function store(Request $request)
{
$post = Post::create([
'user_id' => $request->user()->id,
'title' => $request->title,
'slug' => $request->slug,
'content' => $request->content,
]);
return response()->json([
'message' => 'Post created successfully',
'data' => $post
], 201);
}
Nhớ import:
use Illuminate\Http\Request;
Client gửi:
POST /api/posts
Body:
{
"title": "Laravel 13 REST API",
"slug": "laravel-13-rest-api",
"content": "..."
}
Nếu tạo thành công:
HTTP 201 Created
20. Validation cho API
API vẫn cần Validation giống Website.
Ví dụ:
$request->validate([
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
Nếu dữ liệu không hợp lệ, Laravel có thể trả về lỗi validation dưới dạng JSON đối với request API.
Ví dụ client có thể nhận:
{
"message": "The title field is required.",
"errors": {
"title": [
"The title field is required."
]
}
}
API client có thể dùng thông tin này để hiển thị lỗi cho người dùng.
21. API Update
Ví dụ:
public function update(Request $request, Post $post)
{
$request->validate([
'title' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
$post->update([
'title' => $request->title,
'content' => $request->content,
]);
return response()->json([
'message' => 'Post updated successfully',
'data' => $post
]);
}
Route:
Route::put('/posts/{post}', [PostController::class, 'update']);
Client:
PUT /api/posts/1
22. API Delete
Controller:
public function destroy(Post $post)
{
$post->delete();
return response()->json([
'message' => 'Post deleted successfully'
]);
}
Route:
Route::delete('/posts/{post}', [PostController::class, 'destroy']);
Client:
DELETE /api/posts/1
Có thể trả về:
{
"message": "Post deleted successfully"
}
23. Resource Controller cho API
Thay vì khai báo từng route:
Route::get('/posts', ...);
Route::get('/posts/{post}', ...);
Route::post('/posts', ...);
Route::put('/posts/{post}', ...);
Route::delete('/posts/{post}', ...);
Laravel hỗ trợ resource routing.
Ví dụ:
Route::apiResource('posts', PostController::class);
Lúc này Laravel tạo nhóm route CRUD cho API.
Có thể kiểm tra bằng:
php artisan route:list
Hoặc:
php artisan route:list --path=api
Bạn sẽ thấy các route tương ứng với:
GET /api/posts
POST /api/posts
GET /api/posts/{post}
PUT/PATCH /api/posts/{post}
DELETE /api/posts/{post}
Đây là cách rất phù hợp cho Blog CMS.
24. Hoàn chỉnh PostController cơ bản
Sau khi học xong phần này, chúng ta có thể hình dung Controller:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::published()
->with(['user', 'category'])
->latest('published_at')
->paginate(10);
return response()->json([
'success' => true,
'data' => $posts
]);
}
public function show(Post $post)
{
return response()->json([
'success' => true,
'data' => $post
]);
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
$post = Post::create([
...$validated,
'user_id' => $request->user()->id,
]);
return response()->json([
'success' => true,
'message' => 'Post created successfully',
'data' => $post
], 201);
}
public function update(Request $request, Post $post)
{
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
$post->update($validated);
return response()->json([
'success' => true,
'message' => 'Post updated successfully',
'data' => $post
]);
}
public function destroy(Post $post)
{
$post->delete();
return response()->json([
'success' => true,
'message' => 'Post deleted successfully'
]);
}
}
Đây là API Controller cơ bản.
Tuy nhiên, trong dự án thực tế chúng ta sẽ chưa dừng ở đây.
25. Route API hoàn chỉnh
routes/api.php:
<?php
use App\Http\Controllers\Api\PostController;
use Illuminate\Support\Facades\Route;
Route::apiResource('posts', PostController::class);
Kết quả:
GET /api/posts
POST /api/posts
GET /api/posts/{post}
PUT /api/posts/{post}
PATCH /api/posts/{post}
DELETE /api/posts/{post}
Đây chính là REST API cho resource:
posts
26. Test API bằng trình duyệt
Các request GET đơn giản có thể test trực tiếp bằng trình duyệt.
Ví dụ:
http://127.0.0.1:8000/api/posts
Hoặc:
http://127.0.0.1:8000/api/posts/1
Browser sẽ hiển thị JSON.
Ví dụ:
{
"success": true,
"data": {
"id": 1,
"title": "Laravel 13"
}
}
27. Test API bằng Postman
Khi API có:
GET
POST
PUT
PATCH
DELETE
thì Postman sẽ thuận tiện hơn trình duyệt.
Ví dụ:
GET
http://127.0.0.1:8000/api/posts
POST:
POST
http://127.0.0.1:8000/api/posts
Body:
{
"title": "Bài viết mới",
"slug": "bai-viet-moi",
"content": "Nội dung bài viết"
}
PUT:
PUT
http://127.0.0.1:8000/api/posts/1
DELETE:
DELETE
http://127.0.0.1:8000/api/posts/1
Như vậy Postman có thể đóng vai trò như một client của Laravel API.
28. API không phải là Website
Đây là điểm người mới học Laravel rất dễ nhầm.
Website:
GET /blog
↓
Controller
↓
Blade
↓
HTML
API:
GET /api/posts
↓
Controller
↓
Eloquent
↓
JSON
Hai thứ đều sử dụng Laravel.
Nhưng mục đích khác nhau.
29. Một API có thể phục vụ nhiều ứng dụng
Ví dụ chúng ta có:
Laravel 13 API
│
┌────────────┼────────────┐
↓ ↓ ↓
Website Android iOS
│ │ │
└────────────┼────────────┘
↓
Database
API trở thành tầng trung gian giữa frontend và database.
Ví dụ:
GET /api/posts
Website lấy dữ liệu.
Mobile App cũng gọi:
GET /api/posts
Một ứng dụng React cũng có thể gọi:
GET /api/posts
Không cần xây dựng ba hệ thống backend riêng biệt.
30. REST API trong Blog CMS của chúng ta
Project hiện tại có:
users
categories
posts
Sau khi hoàn thành phần API, chúng ta có thể xây dựng:
/api/posts
/api/categories
/api/users
Ví dụ:
GET /api/posts
GET /api/posts/1
GET /api/categories
GET /api/categories/1
Sau này có thể phát triển tiếp:
POST /api/posts
PUT /api/posts/1
DELETE /api/posts/1
Nhưng vấn đề tiếp theo xuất hiện:
Dữ liệu trả về có nên được đưa thẳng từ Model ra JSON hay không?
Ví dụ Model Post có:
user_id
category_id
view_count
created_at
updated_at
Trong khi frontend có thể chỉ cần:
id
title
slug
excerpt
image
published_at
category
author
Đây chính là lý do chúng ta cần học API Resource.
31. API Resource giải quyết vấn đề gì?
Hiện tại:
return $post;
Laravel có thể chuyển Model thành JSON.
Nhưng chúng ta không kiểm soát tốt cấu trúc dữ liệu.
API Resource cho phép định nghĩa:
Model
↓
Resource
↓
JSON
Ví dụ:
Post
↓
PostResource
↓
{
id,
title,
slug,
excerpt,
image,
category,
author
}
Đây sẽ là nội dung của:
👉 Bài 42 — API Resource
32. API và bảo mật
Một API public không có nghĩa là:
Ai cũng được phép làm mọi thứ.
Ví dụ:
GET /api/posts
có thể public.
Nhưng:
POST /api/posts
PUT /api/posts/1
DELETE /api/posts/1
thì cần kiểm tra người dùng.
Có thể cần:
Authentication
Authorization
Token
Permission
Policy
Đây chính là phần chúng ta sẽ học tiếp trong:
Bài 43 — Sanctum
Bài 44 — API Authentication
Vì vậy trong bài này chúng ta mới chỉ xây dựng REST API cơ bản.
33. Kiến trúc REST API của Blog CMS
Sau khi hoàn thành Phần 9, kiến trúc sẽ có dạng:
Laravel 13
│
┌──────────┴──────────┐
│ │
Website API
│ │
web.php api.php
│ │
Controller Controller
│ │
Blade Resource
│ │
HTML JSON
│ │
└──────────┬──────────┘
↓
Eloquent
↓
MySQL
Đây là một bước rất quan trọng trong quá trình chuyển từ:
Laravel Website
sang:
Laravel Backend API
34. Bài tập thực hành
Bài tập 1
Cài API routing:
php artisan install:api
Kiểm tra:
routes/api.php
Bài tập 2
Tạo:
/api/hello
Trả về:
{
"message": "Hello Laravel 13 API"
}
Bài tập 3
Tạo:
GET /api/posts
Trả về danh sách Post.
Bài tập 4
Tạo:
GET /api/posts/{post}
Trả về một Post.
Bài tập 5
Tạo REST CRUD:
GET /api/posts
GET /api/posts/{post}
POST /api/posts
PUT /api/posts/{post}
DELETE /api/posts/{post}
Có thể sử dụng:
Route::apiResource('posts', PostController::class);
Bài tập 6
Dùng Postman kiểm tra:
GET
POST
PUT
DELETE
và quan sát:
HTTP Status Code
JSON Response
Validation Error
35. Tổng kết
Trong bài này, chúng ta đã làm quen với:
REST API
API là gì?
REST là gì?
HTTP Methods
GET
POST
PUT
PATCH
DELETE
JSON
API routes
php artisan install:apiroutes/api.phpAPI Controller
Route Model Binding
response()->json()HTTP Status Code
Validation
Route::apiResource()Test API bằng Browser
Test API bằng Postman
REST API trong Blog CMS
Quan trọng nhất cần nhớ:
Website
↓
HTML
API
↓
JSON
Và:
GET → Read
POST → Create
PUT → Update
PATCH → Update một phần
DELETE → Delete
Một REST API cơ bản của Blog CMS:
/api/posts
/api/posts/{post}
có thể trở thành backend dùng chung cho:
Website
Mobile App
React
Vue
Next.js
Third-party Application
🎯 Lộ trình tiếp theo
Chúng ta đã có REST API.
Nhưng response hiện tại vẫn còn khá "thô":
return $post;
hoặc:
return Post::all();
Ở bài tiếp theo, chúng ta sẽ học cách kiểm soát chính xác dữ liệu JSON trả về bằng:
🚀 BÀI 42 — API RESOURCE
Luồng xử lý sẽ trở thành:
Database
↓
Eloquent Model
↓
API Resource
↓
JSON
↓
Frontend / Mobile App
Đây là bước rất quan trọng để biến API Laravel thành một API có cấu trúc rõ ràng và phù hợp với dự án thực tế.




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