Conditionally return Model Laravel

I'm very new to Laravel,

I was wondering how can we apply some condition on Model.

Suppose there's a field is_public if this field is false so then only admins can see this data..

I dont wanna do this on controller with where clauses, as in future I might use the Model in many places, also relations..


I think a good solution would be policies: https://laravel.com/docs/8.x/authorization#creating-policies

Policies are classes that organize authorization logic around a particular model or resource. For example, if your application is a blog, you may have a App\Models\Post model and a corresponding App\Policies\PostPolicy to authorize user actions such as creating or updating posts.

You could create a policy for your model like so:

php artisan make:policy YourModelPolicy --model=YourModel

Then maybe something like this for the view method:

public function view(User $user, YourModel $model)
{
    if ($user->isAdmin()) return true;

    if ($model->is_public) return true;

    return false;
}

I think Laravel Global Query Scope is what you looking for.

Global scopes allow you to add constraints to all queries for a given model. Laravel's own soft delete functionality utilizes global scopes to only retrieve "non-deleted" models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints.

Basically, it can apply any clause globally.

What we can do is, define a GLobal Query Scope on our Model, so every time our Model is called, we can check if the user is not a Admin or someone who doesn't have permission to view private data then extend our query with a where clause like where('is_public', true).

here's an example

App\Models\YourModel

   namespace App\Models;

   use Illuminate\Database\Eloquent\Model;
   use Illuminate\Database\Eloquent\Builder; // Dont forget to include

    protected static function booted()
    {
        static::addGlobalScope('visible', function (Builder $builder) {
            if (!optional(auth()->user())->can('The Permission Name')) {
                $builder->where('is_public', true);
            }
        });
    }

There's many more things you can do with Query Scopes, like suppose you dont want this global scope to be used somewhere you can do:

YourModel::withoutGlobalScope('visible')->get();

Learn more about Query Scopes https://laravel.com/docs/8.x/eloquent#query-scopes