I writing a reusable Filtrable trait for laravel projects. I have it working but not perfectly. One part work perfectly why another part not giving expected results
I writing a reusable Filtrable trait for laravel projects. I have it working but not perfectly.
This is my Fliterable trait code
namespace ObrainwaveLaravelQueryFilters;
use IlluminateDatabaseEloquentBuilder;
use IlluminateHttpRequest;
trait Filterable
{
public function scopeFilter(Builder $query, Request | array | null $filters = null) : QueryFilter
{
$filterClass = $this->getFilterClass();
if (! class_exists($filterClass)) {
return $query;
}
$filter = (new $filterClass($filters))
->setBuilder($query)
->apply(); // automatically apply request/array filters
return $filter; // Now you can chain ->status(...)->role(...)->get()
}
protected function getFilterClass(): string
{
return str_replace('Models', 'Filters', static::class) . 'Filter';
}
}
and this is my QueryFilter class code
namespace ObrainwaveLaravelQueryFilters;
use IlluminateDatabaseEloquentBuilder;
use IlluminateHttpRequest;
abstract class QueryFilter
{
protected Builder|null $builder = null;
protected array $filters = [];
/**
* Accept request or array of filters
*/
public function __construct(Request|array|null $filters = null)
{
if ($filters instanceof Request) {
$this->filters = $filters->all();
} elseif (is_array($filters)) {
$this->filters = $filters;
}
}
/**
* Set the query builder instance
*/
public function setBuilder(Builder $builder): static
{
$this->builder = $builder;
return $this;
}
/**
* Apply the filters to the builder
*/
public function apply(): static
{
if (! $this->builder) {
throw new Exception("Query builder is not set. Call setBuilder() first.");
}
foreach ($this->filters as $key => $value) {
if ($value !== null && method_exists($this, $key)) {
$this->$key($value);
}
}
return $this;
}
/**
* Return the underlying builder for final query
*/
public function get()
{
return $this->builder->get();
}
public function first()
{
return $this->builder->first();
}
public function toSql()
{
return $this->builder->toSql();
}
}
So my problem is that it works when I passed the chaining methods
$users2 = User::filter(['status' => 'inactive', 'role' => 'admin'])
->status('inactive')
->role('admin')
->get();
But it returns all rows when I do this
$users1 = User::filter(request())->get();
which means it doesn’t apply the default filtering
I hope anyone can help me spotting my mistakes.