Tucker-Eric/EloquentFilter

Relations with one related method

Closed this issue · 3 comments

Hi, Eric!
Your package is awesome! Thank you!

I just want to ask about filtering by relations where related model should use the same method twice.
For example:

class ConstructionFilter extends BaseModelFilter
{
    public $relations = [
        'owner' => [
            'owner.surname' => 'full_name',
            'owner.name'    => 'full_name',
        ]
    ];
}


class OwnerFilter extends BaseModelFilter
{
    public function fullName($value)
    {
        $this->where('full_name', 'ilike', "%$value%");
    }
}

So if I try to filter construction by owner's name and surname it will use only one of these fields and filter it with owner.fullName.

I guess it happens because of under the hood $relations combine all the related methods and use one whereHas for it.
Of cause I can write two different methods in my OwnerFilter with the same logic but I just want to know is there any way to make work the code which uses different keys and same values for one relation?

Thank you.

Hmm, that's interesting. We could get around this by using the related setup method and updating that fullName filter to expect (or cast) an array it can loop through to chain the queries.

class ConstructionFilter extends BaseModelFilter
{
    public $relations = [
        'owner' => [
            'owner.surname' => 'full_name',
            'owner.name'    => 'full_name',
        ]
    ];

    public ownerSetup()
    {
        // Get all aliases of `full_name`
        $fullNameKeys = array_keys($this->relations["owner"], "full_name");
        
        // Get all values of the input
        $fullNameValues = []
        foreach($fullNameKeys as $key) {
            $val = $this->input($key);
            if($this->includeFilterInput($val)) {
                $fullNameValues[] = $val;
            }
            // Set value to null so it won't get passed to `OwnerFilter` 
            $this->push($key, null)
        }
        
        // Push the values to one key so that is the value that gets passed to the other filter
        $this->push($fullNameKeys[0], $fullNameValues)
    }
}


class OwnerFilter extends BaseModelFilter
{
    public function fullName($values)
    {
        foreach((array) $values as $value) {
            $this->where('full_name', 'ilike', "%$value%");    
        }
    }
}

Thanks!
It works.
A bit more complicated than adding another method to OwnerFilter, but this is exactly what I wanted. Thanks again :)

P.S. I suppose It must be input($key)

>  $val = $this->input($val);

@DevilSAM Ahh, yep! Updated reply