Xây dựng REST API CRUD với Laravel: migration, model và controller

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Laravel cho phép bạn dựng một API quản lý dữ liệu đầy đủ chỉ với vài lệnh Artisan và vài chục dòng code. Bài này sẽ xây API quản lý "ghi chú" với bốn thao tác tạo, đọc, sửa, xóa, đồng thời giới thiệu validation và API Resource.

Chuẩn bị

Bạn cần một dự án Laravel chạy được (xem bài cài đặt Laravel nếu chưa có) và một cơ sở dữ liệu. Với bản Laravel mới, SQLite mặc định thường đã sẵn sàng; nếu muốn dùng MySQL, hãy chỉnh các biến DB_* trong file .env. Các route API được khai báo trong routes/api.php; nếu dự án của bạn chưa có file này, chạy php artisan install:api để bật.

Bước 1: Tạo model, migration và controller

Một lệnh có thể tạo cả ba thứ:

php artisan make:model Note -mc --api

Tùy chọn -m tạo migration, -c tạo controller, còn --api làm controller có sẵn các phương thức index, store, show, update, destroy. Mở file migration trong database/migrations và định nghĩa cột:

public function up(): void
{
    Schema::create('notes', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content')->nullable();
        $table->timestamps();
    });
}

Chạy php artisan migrate để tạo bảng. Trong model app/Models/Note.php, khai báo các trường được phép gán hàng loạt:

class Note extends Model
{
    protected $fillable = ['title', 'content'];
}

Bước 2: Khai báo route

Trong routes/api.php, một dòng là đủ cho cả năm route:

use App\Http\Controllers\NoteController;
use Illuminate\Support\Facades\Route;

Route::apiResource('notes', NoteController::class);

Chạy php artisan route:list để xem danh sách route được tạo ra, thường có tiền tố /api.

Bước 3: Viết controller

Mở app/Http/Controllers/NoteController.php và điền logic:

use App\Models\Note;
use Illuminate\Http\Request;

class NoteController extends Controller
{
    public function index()
    {
        return Note::latest()->get();
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'nullable|string',
        ]);

        $note = Note::create($data);

        return response()->json($note, 201);
    }

    public function show(Note $note)
    {
        return $note;
    }

    public function update(Request $request, Note $note)
    {
        $data = $request->validate([
            'title' => 'sometimes|required|string|max:255',
            'content' => 'nullable|string',
        ]);

        $note->update($data);

        return $note;
    }

    public function destroy(Note $note)
    {
        $note->delete();

        return response()->noContent();
    }
}

Hai điểm đáng chú ý. Thứ nhất, tham số Note $note kích hoạt tính năng route model binding: Laravel tự tìm bản ghi theo id và trả 404 nếu không có. Thứ hai, $request->validate() tự trả lỗi 422 kèm thông báo chi tiết nếu dữ liệu sai, bạn không cần viết tay.

Bước 4: Thử API

Chạy php artisan serve rồi gọi thử bằng curl hoặc Postman. Nhớ gửi header Accept: application/json để Laravel trả lỗi dưới dạng JSON thay vì chuyển hướng.

curl -X POST http://127.0.0.1:8000/api/notes \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"title":"Học Laravel","content":"Làm xong CRUD"}'

curl http://127.0.0.1:8000/api/notes -H "Accept: application/json"

Thử gửi thiếu title, bạn sẽ nhận phản hồi 422 chứa danh sách lỗi theo từng trường.

Bước 5: Định dạng phản hồi với API Resource

Khi muốn kiểm soát chính xác các trường trả về, hãy tạo Resource:

php artisan make:resource NoteResource
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'content' => $this->content,
        'created_at' => $this->created_at->toDateTimeString(),
    ];
}

Sau đó trả về new NoteResource($note) hoặc NoteResource::collection($notes). Cách này giúp bạn thay đổi cấu trúc bảng mà không làm vỡ hợp đồng API với phía ứng dụng khách.

Các bước nâng cao tiếp theo

  • Phân trang bằng paginate() thay vì get() khi dữ liệu lớn.
  • Thêm xác thực bằng Laravel Sanctum và gắn ghi chú với người dùng.
  • Tách validation sang Form Request.
  • Viết test tính năng cho từng endpoint.

Mẹo thiết kế API dễ dùng

Đặt tên tài nguyên ở dạng số nhiều và nhất quán (/notes, /notes/5). Trả mã trạng thái đúng ý nghĩa: 201 khi tạo, 204 khi xóa, 404 khi không tìm thấy, 422 khi dữ liệu sai. Đưa phiên bản vào đường dẫn như /api/v1/notes ngay từ đầu để sau này thay đổi mà không phá vỡ ứng dụng cũ. Luôn viết ít nhất vài bài test tính năng cho mỗi endpoint chính; Laravel hỗ trợ sẵn qua php artisan test, giúp bạn tự tin khi sửa code về sau.

Kết luận

Với apiResource, route model binding và validation tích hợp, Laravel giúp bạn tập trung vào nghiệp vụ thay vì code lặp. Hãy thử mở rộng API với bảng thứ hai và quan hệ giữa hai bảng để luyện Eloquent.

Nếu bạn muốn học Laravel và xây dựng backend chuyên nghiệp, hãy tham khảo các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment