F
Filament17mo ago
RT2023

Trait for user Model

Hi there , I have a multi tenant project the tenants are restaurant name and users belong to one restaurant. I want to show all the users from the user resource when the logged in user has a Admin role. Otherwise, managers can only see restaurants belonging to the user , restaurant_id. I was able to write a trait that works great when i have users logged in. Once I sign out the user I get the following message. the code of the trait is: <?php namespace App\Traits; use Illuminate\Database\Eloquent\Builder; trait FilterByRestaurant { protected static function boot(): void { parent::boot(); $restaurantId = auth()->user()->restaurant_id; self::creating(function($model) use ($restaurantId){ $model->restaurant_id=$restaurantId; }); if ( ! auth()->user()->hasRole('Admin')) { self::addGlobalScope(function(Builder $builder) use($restaurantId){ $builder->where('restaurant_id',$restaurantId); }); } } } Can you please help me to figure out what my issue is? Thanks
18 Replies
cheesegrits
cheesegrits17mo ago
Not sure why you wouldn't just put the auth check in the global scope directly. But yeah, if you aren't logged in, auth()->user() returns null. So you'd have to nullsafe it like ... $restaurantId = auth()->user()?->restaurant_id; ... then test for restaurantId being null and do whatever you need for that situation.
RT2023
RT2023OP17mo ago
Thanks Hugh, I did what you recommended but im getting the same error
Vp
Vp17mo ago
$restaurantId = auth()->user()?->restaurant_id;

if ($restaurantId) {
self::creating(....)
}
$restaurantId = auth()->user()?->restaurant_id;

if ($restaurantId) {
self::creating(....)
}
Did you do like this?
RT2023
RT2023OP17mo ago
VP,
RT2023
RT2023OP17mo ago
I did it but now im getting
Vp
Vp17mo ago
You need to put if ( ! auth()->user()->hasRole('Admin')) { inside if ($restaurantId) also. the error came because you don't have auth()->user()
RT2023
RT2023OP17mo ago
<?php namespace App\Traits; use Illuminate\Database\Eloquent\Builder; trait FilterByRestaurant { protected static function boot(): void { parent::boot(); $restaurantId = auth()->user()?->restaurant_id; if ($restaurantId){ self::creating(function($model) use ($restaurantId){ $model->restaurant_id=$restaurantId; }); } if ( ! auth()->user()->hasRole('Admin')) { if($restaurantId){ self::addGlobalScope(function(Builder $builder) use($restaurantId){ $builder->where('restaurant_id',$restaurantId); }); } }
RT2023
RT2023OP17mo ago
still get the error
cheesegrits
cheesegrits17mo ago
Same problem, you aren't nullsafing your second call to auth()->user(). And I'm still really confused by the approach you are taking. COnditionally adding a scope, rather than just having a global scope which itself tests the user's role.
RT2023
RT2023OP17mo ago
the reason im doing it this way is because i only want managers to see only the users corresponding to the restaurant where the belong to and the admins to see all of them. Im open to adding the global scope but not really sure where to define that
cheesegrits
cheesegrits17mo ago
https://laravel.com/docs/10.x/eloquent#global-scopes Then just do your testing for restaurant_id / hasRole in the apply() method.
Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.
RT2023
RT2023OP17mo ago
Thanks Hugh, I will investigate this approach
cheesegrits
cheesegrits17mo ago
Your use case is exactly what global scopes are for. Or, you could add a local scope to the model, and include it in the table query on your resource. But in a tenancy environment, it usually belongs globally.
John
John17mo ago
Additionally, you can always ->withoutGlobalScope / Scopes() if needed in an exceptional case.
cheesegrits
cheesegrits17mo ago
Should probably also read up on policies, so non admins can't edit resources they don't own by just changing an ID on an edit link.
RT2023
RT2023OP17mo ago
Thanks All , I was able to figure out a solution
cheesegrits
cheesegrits17mo ago
So how did you do it in the end?
RT2023
RT2023OP17mo ago
Hugh, I did try the global scope and didn't work either. My code in the scope was $restaurantId = auth()->user()->restaurant_id; $builder->where('restaurant_id','=',$restaurantId); however all I got was a white screen. What I did was to add this code to the user resource / listuser page protected function getTableQuery():Builder{ $restaurantId = auth()->user()->restaurant_id; return User:: where('restaurant_id', '=', $restaurantId); } this way i was able to filter the users per restaurant. I created a table in the dashboard to see all the users for all restaurants when an admin was logged in. not the most elegant solution but for my use does the job. thanks all for your input I also tried to add a when statement to the protected function getTableQuery() but it seems its not allowed with that function. Hence the table in the dashboard An update, I was finally able to make it work with the original trait. The issue was the exclamation mark in the code.
Want results from more Discord servers?
Add your server