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.


Laravel 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.


1. Thay thế 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.


2. when() truyền giá trị vào Closure

Mộ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();

3. Nhiều điều kiện với 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.


4. 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ả:

  • name
  • email

5. when() với khoảng thời gian

Mộ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.


6. 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.


7. when() với giá trị mặc định

when() 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

8. when() với Eloquent Relationship

when() 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().


9. 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.


10. Một lưu ý quan trọng với giá trị 0

Cầ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.


11. when() không chỉ dành cho Eloquent

Bạ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ả:

  • Eloquent
  • Query Builder
  • API filtering
  • Search
  • Sorting
  • Date filtering
  • Relationship filtering

12. Ví dụ thực tế hoàn chỉnh

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.


13. Khi nào nên sử dụng when()?

when() đặc biệt phù hợp khi:

  • Query có nhiều điều kiện tùy chọn.
  • Xây dựng API filter.
  • Xây dựng chức năng tìm kiếm.
  • Filter dữ liệu theo ngày.
  • Filter theo Relationship.
  • Sort dữ liệu dựa trên Request.
  • Muốn giảm số lượng 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.


Kết luận

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.

Categories:

Leave Comment

Tháng 9 2026
H B T N S B C
 123456
78910111213
14151617181920
21222324252627
282930