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