HPage
HPage

Reputation: 1503

Filtering Eloquent

I am trying to filter my Eloquent model collections based on if a user has access to the model or not.

My current method works, but it is really slow so I am wondering if there is a more performant way to do it?

I have a userHasAccess() method on every model in the collection. It uses Laravel's ACL Features to determine if the user has access to the model:

public function userHasAccess()
{
    if (Auth::user()->can('show', $this)) {
        return true;
    }

    return false;
}

I then override the newCollection() method on the model:

public function newCollection(array $models = Array())
{
    $collection = new Collection($models);

    $collection = $collection->filter(function($model)
    {
        if($model->userHasAccess())
            return true;
    });

    return $collection;
}

The policy method looks like this:

public function show(User $user, Quote $quote)
{
    if(!$quote->customer)
        return false;

    if(($user->id === $quote->user_id))
        return true;

    if($user->hasRole(['super-admin','admin']))
        return true;

    return false;
}

Is there a better way to do this? Especially in terms of performance?

Upvotes: 3

Views: 212

Answers (1)

RDelorier
RDelorier

Reputation: 777

You could add the logic to the query and speed it up dramatically

$query = User::query();

if(!Auth::user()->hasRole(['super-admin','admin'])){
    $query->where('user_id','=',Auth::id);
}

$data = $query->get();

You could do this on a wider scale using a scope

class User extends Model
{
    public function scopeLimitByUser($query)
    {
        if(!Auth::user()->hasRole(['super-admin','admin'])){
            $query->where('user_id','=',Auth::id);
        }
    }
}

Then for the quote customer you can add a where to the query

$query->whereNotNull('customer_id');

Upvotes: 2

Related Questions