Skip to content

Instantly share code, notes, and snippets.

@jfreites
Last active December 8, 2024 15:14
Show Gist options
  • Save jfreites/6aded260903c9f0f6ce5b8a986be272f to your computer and use it in GitHub Desktop.
Save jfreites/6aded260903c9f0f6ce5b8a986be272f to your computer and use it in GitHub Desktop.
Filtering request in Laravel
<?php
namespace App\Support\Filters;
use Illuminate\Database\Eloquent\Builder;
final class FilterBuilder
{
public function __construct(protected Builder $query, protected array $filters, protected string $namespace)
{
}
public function apply()
{
foreach ($this->filters as $name => $value) {
$normalizedName = ucfirst($name);
$class = $this->namespace . "\\{$normalizedName}";
if (! class_exists($class)) {
continue;
}
(new $class($this->query))->handle($value);
}
return $this->query;
}
}
<?php
namespace Domain\Shared\Filters;
interface FilterInterface
{
public function handle(?string $value): void;
}
<?php
namespace Domain\User\Filters;
use App\Support\Filters\QueryFilter;
use Domain\Shared\Filters\FilterInterface;
class Name extends QueryFilter implements FilterInterface
{
public function handle(?string $value): void
{
$this->query->where('name', $value);
}
}
<?php
namespace App\Support\Filters;
use Illuminate\Database\Eloquent\Builder;
abstract class QueryFilter
{
public function __construct(protected Builder $query)
{
}
}
<?php
namespace Domain\User\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
public function scopeFilterBy($query, array $filters): Builder
{
return (new FilterBuilder(
$query, $filters, 'Domain\User\Filters'
))->apply();
}
}
<?php
namespace App\Http\Api\Controllers\User;
use App\Http\Api\Controllers\ApiController;
use Bamba\Beneficiary\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Symfony\Component\HttpFoundation\Response;
class UserController extends ApiController
{
// Example request: /beneficiary?name=jon
public function getPaginatedByChannel(Request $request): LengthAwarePaginator
{
$users = User::with('otherModel')->filterBy($request->all())->get();
return $users->paginate();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment