Service-Repository Pattern trong Laravel: Bạn Hay Thù?

· 3 min read

Nếu bạn tìm kiếm "Laravel Best Practices", bạn sẽ chắc chắn tìm thấy bài viết bảo bạn tạo interface, repository, và service cho mỗi model.

Dừng lại.

"Repository Pattern" đến từ Domain Driven Design (DDD) để tách domain logic khỏi data access. Trong Java hoặc C#, nơi ORM là các datamapper nặng, điều này rất quan trọng. Trong Laravel, Eloquent sử dụng Active Record pattern, cố ý kết hợp dữ liệu và hành vi.

Vậy, chính xác khi nào Repository Pattern hữu ích?

Vấn Đề Với "Repository Mặc Định"

Hầu hết các implementation "Repository" trong Laravel trông như thế này:

class UserRepository {
    public function find($id) {
        return User::find($id);
    }
}

Đây là một wrapper không thêm giá trị gì. Nó loại bỏ sự biểu đạt của Eloquent (User::where(...)->get()) và thay thế bằng một phương thức generic. Bạn mất IDE autocompletion, scope, và khả năng dễ dàng eager load relationship.

Khi Nào Nên Dùng Repository?

1. Thay Đổi Implementation

Nếu nguồn dữ liệu có thể thay đổi từ MySQL sang API bên ngoài (ví dụ: ElasticSearch, Redis) trong tương lai. Spoiler: Trong 99% dự án, bạn sẽ không bao giờ đổi database.

2. Testing (Mocking)

Nếu yêu cầu unit testing nghiêm ngặt và bạn muốn mock hoàn toàn data access mà không chạm DB. Tuy nhiên, SQLite in-memory testing của Laravel hoặc trait RefreshDatabase thường đủ nhanh.

3. Đóng Gói Query Phức Tạp

Nếu bạn có query dài 50 dòng và được dùng ở 10 nơi. Nhưng... scope cũng có thể xử lý việc này.

Giải Pháp Thay Thế: Service Layer

Thay vì wrap Eloquent, tập trung wrap Business Logic.

Sai (Fat Controller):

public function store(Request $request) {
    // Validation...
    $user = User::create(...);
    $subscription = Subscription::create(...);
    Mail::to($user)->send(...);
    return response(...);
}

Tốt Hơn (Service Class):

class UserRegistrationService {
    public function register(array $data) {
        return DB::transaction(function() use ($data) {
            $user = User::create($data);
            $this->subscriptionService->createDefault($user);
            return $user;
        });
    }
}

Khi Nào Tránh Repository

  • Bạn đang xây dựng ứng dụng CRUD.
  • Bạn cần toàn bộ sức mạnh của Eloquent (collection, scope, relationship).
  • Bạn đang tối ưu cho tốc độ phát triển.

Kết Luận

Đừng mù quáng tuân theo các pattern enterprise.

  1. Bắt đầu với Controller + Eloquent.
  2. Di chuyển logic sang Service Class khi nó phức tạp.
  3. Sử dụng Repository CHỈ KHI bạn cần abstract hoàn toàn cơ chế lưu trữ (ví dụ: Hexagonal Architecture).

Giữ cho đơn giản.

Bình luận