Filterable від Abdalrhman Emad Saad — це Laravel-пакет, що пропонує структурований підхід до фільтрації запитів Eloquent. Замість того, щоб вручну прописувати умови в контролерах, він використовує спеціальні класи фільтрів та кілька спеціалізованих рушіїв (engines) для перетворення HTTP-запитів у запити до бази даних.
Ключова перевага пакета — модульна архітектура рушіїв. Це дозволяє розробникам обирати той стиль фільтрації, який найкраще відповідає вимогам фронтенду.
# Основне використання
Для початку роботи додайте trait HasFilterable до вашої моделі та за бажанням вкажіть клас фільтра за замовчуванням:
namespace App\Models;
use App\Http\Filters\TaskFilter;
use Kettasoft\Filterable\Traits\HasFilterable;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
use HasFilterable;
protected $filterable = TaskFilter::class;
}
Тепер фільтри можна застосовувати безпосередньо в контролері. Пакет автоматично розпізнає параметри запиту:
public function index()
{
// Автоматично використовує прив'язаний TaskFilter
return Task::filter()->paginate();
}
# Різні рушії фільтрації
Filterable містить чотири вбудовані рушії для роботи з різними форматами запитів:
- Invokable Engine: пов'язує ключі запиту з конкретними методами у вашому класі фільтра. Підтримує PHP 8 annotations для кастингу типів, валідації та авторизації.
- Ruleset Engine: обробляє прості запити типу «поле-оператор-значення». Зручно для ресурсних списків, наприклад:
?filter[stock][gte]=500&filter[category]=electronics. - Expression Engine: розширює Ruleset, додаючи підтримку глибоких зв'язків Eloquent через крапку. Наприклад, фільтрація тікетів за рівнем підписки клієнта:
?filter[user.subscription.plan][eq]=premium. - Tree Engine: працює з ієрархічними JSON-структурами (з логікою AND/OR), рекурсивно перетворюючи їх на групи
whereтаorWhereв Eloquent.
# Анотації PHP 8 для логіки фільтрів
Рушій Invokable використовує атрибути PHP 8 для автоматизації рутинних завдань: очищення вхідних даних та валідації безпосередньо в методах фільтра. Це дозволяє задавати обмеження (обов'язкові поля або доступ за ролями) на рівні конкретного методу:
class TaskFilter extends Filterable
{
protected $filters = ['title', 'priority', 'due_date'];
protected function title(Payload $payload)
{
// Використання asLike() для автоматичного додавання знаків %
return $this->builder->where('title', 'like', $payload->asLike('both'));
}
#[Cast('integer')]
#[In([1, 2, 3])]
protected function priority(Payload $payload)
{
return $this->builder->where('priority_level', $payload->value);
}
#[Authorize('manage-tasks')]
#[Required]
#[Date]
protected function due_date(Payload $payload)
{
return $this->builder->whereDate('deadline', '<=', $payload->value);
}
}
# Вбудована система кешування
Пакет має інтегровану систему кешування, розроблену спеціально для конвеєра фільтрації. Вона підтримує тегування, умовне кешування та ізоляцію за користувачем або тенантом (tenant):
// Кешувати залишки на складі на 30 хвилин, ізольовано за ID філії
Product::filter()->cache(1800)->scopeByTenant($branchId)->get();
// Кешувати результати лише для гостей, щоб зменшити навантаження на публічні списки
Listing::filter()->cacheWhen(auth()->guest(), 3600)->cacheTags(['public_listings'])->get();
Filterable також підтримує автоматичну інвалідацію кешу при створенні, оновленні або видаленні моделей.
# CLI та інструменти налагодження
Для зручності розробки Filterable надає кілька команд Artisan:
php artisan filterable:setup: початкове налаштування конфігурації.php artisan filterable:make-filter: створення нового класу фільтра.php artisan filterable:test: тестування фільтра з тестовими даними (наприклад,--data="status=active").php artisan filterable:inspect: перегляд деталей фільтра, його рушіїв та правил валідації.php artisan filterable:discover: автоматична реєстрація класів фільтрів у застосунку.
# Встановлення
Встановити пакет можна через Composer:
composer require kettasoft/filterable
Пакет вимагає PHP 8.1 або вище та підтримує Laravel версій 10–12. Більше інформації доступно в документації Filterable або в репозиторії на GitHub.