Tucker-Eric / EloquentFilter

An Eloquent Way To Filter Laravel Models And Their Relationships
http://tucker-eric.github.io/EloquentFilter
MIT License
1.72k stars 120 forks source link

Status if result is filtered #90

Closed pahy closed 5 years ago

pahy commented 5 years ago

Is there a way to find out if any of the modelfilter functions was triggered? Or the result is filtered at least? Thanks in advance.

Tucker-Eric commented 5 years ago

All the input used to filter a model is stored in a protected $filtered array on the initial model so you'd be able to access it through the builder like:

// On your model
class MyModel extends Model
{
    use Filterable;
    //Model logic
    public function getFilterInput()
    {
        return $this->filtered;
    }
}

// Where your query is.
$builder = MyModel::filter($request->all());
$filteredInput = $builder->getModel()->getFilterInput();
$result = $builder->get();
pahy commented 5 years ago

Please let me explain my requirement in more detail. The $filtered is fine, but contains everything included in my search query. And the filtermodel-functions might only affect a subset of the given filters from the input. The user queries something like filter[lastname]=Doe&filter[doesnotexist]=anything There is a filtermodel-function for 'lastname', but not for 'doesnotexist'. Is there a way to get a automated list/array, which filtermodel-function was triggered? Something containing the filter for 'lastname', but none for 'doesnotexist', because there is no filtermodel-function for "doesnotexist"? The result could look like

[
  "lastname" => ["Doe"]
]

or in a luxurious finish anything in the way like

[
  "ModelFilter::lastname"=>["Doe"]
]
Tucker-Eric commented 5 years ago

Ahhh, I see.

I'd recommend doing it in a setup method that gets called, if present on a model filter, initially regardless of input. Then creating a setter on your model to set the filtered input (since that property is protected).

public function setup()
{
    $filtered = [];
    foreach ($this->input as $key => $val) {        
        if ($this->methodIsCallable($method = $this->getFilterMethod($key))) {
            $filtered[static::class . '::' . $method] = $val;
        }
    }

    $this->query->getModel()->setFiltered($filtered);
}

You could even extend the Filterable trait and add the setter to that to avoid creating a setter for every model that you want to track the filtered input.

Or you could extend the ModelFilter class and put this logic there with an accessible variable to store the filtered input across instances.

pahy commented 5 years ago

Thank you. Flawless!