Laravel when() – Conditional Query cực tiện
- Home
- Laravel when() – Conditional Query cực tiện
Khi xây dựng ứng dụng Laravel, chúng ta thường gặp tình huống phải thêm điều kiện vào Query dựa trên dữ liệu đầu vào.
Cách truyền thống thường là sử dụng if:
$query = User::query();
if ($request->filled('status')) {
$query->where('status', $request->status);
}
if ($request->filled('role')) {
$query->where('role', $request->role);
}
$users = $query->get();
Code này hoàn toàn đúng, nhưng nếu có nhiều điều kiện thì Controller sẽ trở nên dài và khó đọc.
Laravel cung cấp when() để giải quyết vấn đề này một cách rất gọn gàng.
when() là gì?when() cho phép bạn chỉ thêm điều kiện vào Query khi một giá trị thỏa mãn điều kiện.
Cú pháp cơ bản:
$query->when($condition, function ($query) {
// Query được thực hiện khi condition đúng
});
Ví dụ:
$users = User::query()
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->get();
Nếu $request->status có giá trị, Laravel sẽ thêm:
WHERE status = 'active'
Nếu $request->status không có giá trị, điều kiện where() sẽ không được thêm vào Query.
if bằng when()Ví dụ thông thường:
$query = User::query();
if ($request->filled('status')) {
$query->where('status', $request->status);
}
$users = $query->get();
Có thể viết ngắn hơn:
$users = User::query()
->when($request->filled('status'), function ($query) use ($request) {
$query->where('status', $request->status);
})
->get();
Cách này đặc biệt hữu ích khi xây dựng API có nhiều bộ lọc.
when() truyền giá trị vào ClosureMột điểm rất tiện của when() là Laravel có thể truyền giá trị của $condition vào Closure.
Thay vì:
->when($request->status, function ($query) use ($request) {
$query->where('status', $request->status);
})
Có thể viết:
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
Code ngắn và dễ đọc hơn.
Ví dụ:
$users = User::query()
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->get();
when()Đây là trường hợp when() phát huy hiệu quả rõ nhất.
Giả sử API có các tham số:
status
role
search
Thay vì viết nhiều if:
$query = User::query();
if ($request->status) {
$query->where('status', $request->status);
}
if ($request->role) {
$query->where('role', $request->role);
}
if ($request->search) {
$query->where('name', 'like', '%' . $request->search . '%');
}
$users = $query->get();
Có thể viết:
$users = User::query()
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->when($request->role, function ($query, $role) {
$query->where('role', $role);
})
->when($request->search, function ($query, $search) {
$query->where('name', 'like', '%' . $search . '%');
})
->get();
Mỗi điều kiện được tách thành một đoạn rõ ràng.
when() với nhiều where()Không chỉ thêm một điều kiện, Closure có thể chứa nhiều Query.
Ví dụ:
$users = User::query()
->when($request->search, function ($query, $search) {
$query->where(function ($query) use ($search) {
$query->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
})
->get();
Khi có search, Laravel sẽ tìm kiếm trên cả:
nameemailwhen() với khoảng thời gianMột trường hợp thường gặp khi xây dựng API là lọc dữ liệu theo ngày.
Ví dụ:
$orders = Order::query()
->when($request->start_date, function ($query, $date) {
$query->whereDate('created_at', '>=', $date);
})
->when($request->end_date, function ($query, $date) {
$query->whereDate('created_at', '<=', $date);
})
->get();
Nếu client chỉ gửi:
start_date=2026-09-01
Query chỉ thêm điều kiện ngày bắt đầu.
Nếu gửi cả:
start_date=2026-09-01
end_date=2026-09-07
Laravel sẽ áp dụng cả hai điều kiện.
when() với orderBy()when() không chỉ dùng với where().
Bạn cũng có thể sử dụng nó với orderBy().
Ví dụ:
$users = User::query()
->when($request->sort === 'name', function ($query) {
$query->orderBy('name');
})
->when($request->sort === 'newest', function ($query) {
$query->latest();
})
->get();
Request:
?sort=name
sẽ sắp xếp theo tên.
Request:
?sort=newest
sẽ lấy dữ liệu mới nhất trước.
when() với giá trị mặc địnhwhen() còn hỗ trợ tham số thứ ba để xử lý trường hợp điều kiện không đúng.
Cú pháp:
$query->when(
$condition,
function ($query) {
// condition đúng
},
function ($query) {
// condition sai
}
);
Ví dụ:
$users = User::query()
->when(
$request->status,
function ($query, $status) {
$query->where('status', $status);
},
function ($query) {
$query->where('status', 'active');
}
)
->get();
Nếu có status, Laravel lọc theo status được truyền vào.
Nếu không có status, mặc định chỉ lấy:
active
when() với Eloquent Relationshipwhen() cũng rất hữu ích khi query Relationship.
Ví dụ có Model:
Post
và:
Category
Bạn muốn lọc bài viết theo category nếu người dùng truyền category_id.
$posts = Post::query()
->when($request->category_id, function ($query, $categoryId) {
$query->whereHas('category', function ($query) use ($categoryId) {
$query->where('id', $categoryId);
});
})
->get();
Nếu không có category_id, Laravel không thêm whereHas().
when() trong API FilterĐây là một pattern rất phù hợp cho REST API.
Ví dụ API:
GET /api/products
có thể nhận:
?category=phone
&brand=apple
&min_price=500
&max_price=2000
&search=iphone
Query:
$products = Product::query()
->when($request->category, function ($query, $category) {
$query->where('category', $category);
})
->when($request->brand, function ($query, $brand) {
$query->where('brand', $brand);
})
->when($request->min_price, function ($query, $price) {
$query->where('price', '>=', $price);
})
->when($request->max_price, function ($query, $price) {
$query->where('price', '<=', $price);
})
->when($request->search, function ($query, $search) {
$query->where('name', 'like', "%{$search}%");
})
->paginate(20);
Đây là cách rất gọn để xây dựng API có nhiều bộ lọc tùy chọn.
0Cần cẩn thận khi sử dụng:
->when($request->price, ...)
Nếu giá trị có thể bằng 0, điều kiện có thể bị đánh giá là false.
Ví dụ:
$request->price = 0;
Nếu muốn kiểm tra xem parameter có thực sự được gửi hay không, nên sử dụng:
->when($request->has('price'), function ($query) use ($request) {
$query->where('price', $request->price);
})
Hoặc với Form Request/API:
->when($request->filled('price'), function ($query, $price) {
$query->where('price', $price);
})
Việc lựa chọn has() hay filled() phụ thuộc vào việc bạn muốn chấp nhận giá trị rỗng hay không.
when() không chỉ dành cho EloquentBạn cũng có thể sử dụng when() với Query Builder.
Ví dụ:
$users = DB::table('users')
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->when($request->role, function ($query, $role) {
$query->where('role', $role);
})
->get();
Vì vậy, when() rất hữu ích cho cả:
Giả sử xây dựng API tìm kiếm đơn hàng:
public function index(Request $request)
{
$orders = Order::query()
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->when($request->customer_id, function ($query, $customerId) {
$query->where('customer_id', $customerId);
})
->when($request->start_date, function ($query, $date) {
$query->whereDate('created_at', '>=', $date);
})
->when($request->end_date, function ($query, $date) {
$query->whereDate('created_at', '<=', $date);
})
->when($request->search, function ($query, $search) {
$query->where('order_code', 'like', "%{$search}%");
})
->latest()
->paginate(20);
return response()->json($orders);
}
Controller lúc này không cần hàng loạt:
if (...)
mà Query vẫn rất dễ đọc.
when()?when() đặc biệt phù hợp khi:
if trong Controller.Ví dụ thay vì:
if ($request->status) {
$query->where('status', $request->status);
}
if ($request->role) {
$query->where('role', $request->role);
}
if ($request->search) {
$query->where('name', 'like', "%{$request->search}%");
}
Có thể viết:
$query
->when($request->status, fn ($q, $v) => $q->where('status', $v))
->when($request->role, fn ($q, $v) => $q->where('role', $v))
->when($request->search, fn ($q, $v) => $q->where('name', 'like', "%{$v}%"));
Code ngắn hơn nhưng vẫn giữ được logic rõ ràng.
Laravel when() là một trong những method nhỏ nhưng rất hữu ích khi làm việc với Eloquent và Query Builder.
Thay vì viết nhiều if để kiểm tra Request trước khi thêm điều kiện, bạn có thể xây dựng Query theo kiểu fluent:
$query
->when($condition1, ...)
->when($condition2, ...)
->when($condition3, ...);
Đặc biệt với các REST API có nhiều bộ lọc, when() giúp Controller ngắn gọn, dễ đọc và dễ mở rộng hơn.
Nếu bạn đang viết Laravel API, đây là một thủ thuật rất đáng đưa vào coding pattern hàng ngày.