
Vì sao cần Best Practices cho Eloquent?
Eloquent giúp bạn phát triển rất nhanh. Nhưng khi project lớn:
- Model trở nên quá to
- Query khó kiểm soát
- Performance giảm dần
- Bug authorization xuất hiện
Trong production, Eloquent cần được dùng có chiến lược.
Tài liệu chính thức:
https://laravel.com/docs/eloquent
1️⃣ Tránh Fat Model
Một sai lầm phổ biến là dồn toàn bộ business logic vào model.
Ví dụ anti-pattern:
class Order extends Model
{
public function calculateTotal() { ... } public function applyDiscount() { ... } public function sendInvoice() { ... } public function syncToCRM() { ... }
}
Model nên:
- Đại diện dữ liệu
- Chứa relationship
- Chứa scope
- Không chứa orchestration logic lớn
Business flow nên đặt trong:
- Service
- Action class
- Use case layer
2️⃣ Luôn Kiểm Soát N+1
Trong production:
- Không bao giờ tin rằng eager loading đã đủ
- Không tin rằng query nhỏ là an toàn
Nên bật:
Model::preventLazyLoading();
Điều này giúp phát hiện N+1 sớm trong dev.
3️⃣ Không Lạm Dụng Relationship Lồng Nhau
Ví dụ nguy hiểm:
User::with('posts.comments.author.profile')->get();
Query sâu như vậy có thể:
- Tăng memory
- Tăng join complexity
- Làm query plan xấu
Giải pháp:
- Tách query
- Dùng DTO
- Dùng custom select
4️⃣ Không Dùng Eloquent Cho Mọi Thứ
Eloquent rất tiện, nhưng không phải tối ưu cho:
- Bulk insert lớn
- Report phức tạp
- Data warehouse query
Ví dụ insert lớn:
DB::table('logs')->insert($largeDataArray);
Nhanh hơn nhiều so với loop create().
5️⃣ Sử Dụng withCount Thay Vì Load Toàn Bộ
Nếu chỉ cần số lượng:
User::withCount('posts')->get();
Không nên:
$user->posts->count();
Tránh load collection không cần thiết.
6️⃣ Index Là Bắt Buộc
Nếu bạn dùng:
- where
- join
- orderBy
Nhưng không có index → query sẽ chậm theo thời gian.
Trong migration:
$table->index('user_id');
Luôn kiểm tra bằng:
EXPLAIN SELECT ...
Đọc thêm:
https://use-the-index-luke.com/
7️⃣ Không Tin Vào Magic
Eloquent làm nhiều thứ phía sau:
- Auto cast
- Auto timestamp
- Auto relationship resolve
Nếu không hiểu, bạn có thể:
- Trigger query ngoài ý muốn
- Tạo bug performance
- Gây memory leak
Hiểu rõ lifecycle model là bắt buộc khi scale.
8️⃣ Sử Dụng Chunk hoặc Cursor Cho Data Lớn
Sai:
User::all();
Đúng:
User::chunk(100, function ($users) {
foreach ($users as $user) {
// xử lý
}
});
Hoặc:
User::cursor();
Giúp tiết kiệm memory đáng kể.
9️⃣ Tách Query Logic Ra Khỏi Controller
Sai:
public function index()
{
return User::where('active', 1)
->where('role', 'admin')
->whereDate('created_at', '>=', now()->subMonth())
->get();
}
Tốt hơn:
User::active()
->role('admin')
->recent()
->get();
Giữ controller mỏng và dễ đọc.
Kết luận
Eloquent trong production nên:
- Giữ model gọn
- Tránh fat model
- Kiểm soát N+1
- Tối ưu query
- Không lạm dụng abstraction
- Theo dõi performance
Eloquent rất mạnh. Nhưng nếu dùng sai cách, nó sẽ làm hệ thống của bạn chậm dần theo thời gian mà bạn không nhận ra.
