Khi bạn đối mặt với việc lặp lại nhiều câu truy vấn giống nhau. Laravel Eloquent Builder Macro sẽ là công cụ cứu cánh cho sự trừu tượng hóa, giúp mã nguồn của bạn trở nên linh hoạt hơn và giảm bớt gánh nặng của sự phức tạp.
Ví dụ một chút nhé:
Bạn đang muốn tìm kiếm các ứng viên có xuất hiện từ {$key} trong tên hoặc địa chỉ. Đoạn code của bạn trông sẽ như thế này:
Candidate::query()
->where('name', 'like', "%{$key}%")
->orWhere('address', 'like', "%{$key}%")
->get();
Và mỗi lần thêm trường tìm kiếm, bạn sẽ phải viết thêm vài dòng where như thế này nữa, và còn nhiều nơi khác trong source code đang làm điều tương tự, quá nhiều where “like” đúng không nào.
Sử dụng Laravel Eloquent Builder Macro
Bạn chỉ cần vào App\Providers\AppServiceProvider và khai báo đoạn code sau vào phương thức boot().
public function boot()
{
Builder::macro('whereLike', function ($column, $value = null, $boolean = 'and') {
return $this->where($column, 'like', $value, $boolean);
});
}
Hoặc bạn cũng có thể đăng ký một Service Providers như sau:
1. Sử dụng Artisan Command:
php artisan make:provider MarcoServiceProvider
Lệnh này sẽ tạo ra một file mới tên là MarcoServiceProvider.php trong thư mục app/Providers.
2. Khởi tạo chức năng với phương thức boot():
public function boot()
{
Builder::macro('whereLike', function ($column, $value = null, $boolean = 'and') {
return $this->where($column, 'like', $value, $boolean);
});
}
3. Đăng ký Service Provider:
Mở file config/app.php và thêm Service Provider vào mảng providers.
'providers' => [
// ...
App\Providers\MarcoServiceProvider::class,
],
Bây giờ bạn đã có thể dùng câu truy vấn whereLike rồi (happy).
Đoạn code ví dụ sẽ được viết lại như thế này:
Candidate::query()
->whereLike('name', "%{$key}%")
->whereLike('address', "%{$key}%", 'or')
->get();
Làm một cái gì đó gọn hơn nhé.
// App\Providers\MacroServiceProvider
Builder::macro('whereLike', function ($columns = [], $value = null, $boolean = 'and') {
return array_map(function ($column) use ($value, $boolean) {
$this->where($column, 'like', $value, $boolean);
}, $columns);
});
Và khi sử dụng thì bạn chỉ cần truyền một array vào whereLike là đã ok rồi.
Candidate::query()
->whereLike(['name', 'address'], "%{$key}%", 'or')
->get();
Nhưng nếu một lúc nào đó, bạn chỉ muốn tìm kiếm những ứng viên có đang hoạt động (status = 1) thôi thì whereLike này có thể sẽ không còn đúng nữa. Ví dụ:
Candidate::query()
->whereLike(['name', 'address'], "%{$key}%", 'or')
->where('status', 1)
->get();
Đoạn code được viết lại:
Candidate::query()
->where('name', 'like', "%{$key}%")
->orWhere('address', 'like', "%{$key}%")
->where('status', 1)
->get();
Vậy bây giờ, việc cần làm là định nghĩa thêm một truy vấn mới và tái sử dụng whereLike.
Builder::macro('subWhereLike', function ($columns = [], $value = null, $boolean = 'or') {
return $this->where(function ($q) use ($columns, $value, $boolean) {
$q->whereLike($columns, $value, $boolean);
});
});
Đã ổn hơn rồi, câu truy vấn đã được viết lại.
Candidate::query()
->where(function ($q) use ($key) {
$q->where('name', 'like', "%{$key}%")
$q->orWhere('address', 'like', "%{$key}%")
})
->where('status', 1)
->get();
Trong một vài trường hợp, bạn mong muốn thêm một câu truy vấn khác nữa thì việc truyền thêm một Closure là điều cần thiết.
Builder::macro('subWhereLike', function ($columns = [], $value = null, $boolean = 'or', Closure $closure = null) {
$query = $this->where(function ($q) use ($columns, $value, $boolean, $closure) {
$q->whereLike($columns, $value, $boolean);
if ($closure !== null) {
$closure($q);
}
});
return $query;
});
Sử dụng thôi nào!
Candidate::query()
->subWhereLike(['email', 'lastname'], "%{$key}%", 'or',
function ($query) use ($key) {
$query->orWhere('phone', $key);
})
->where('status', 1)
->get();
Hết rồi, bạn hãy thực hành và cảm nhận nhé!!!
1 comment
Quá tuyệt vời 👏 😎