Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

Master Admin: Managing Teams/Clinics

Premium
4:33

The teams (clinics) will be managed by a user with a Master Admin role. That Master Admin will not see the users and the tasks of each clinic. They will just manage the teams.

For simplicity, in this tutorial, we will build just the team features of list and create, without edit/delete functionality.

First, let's talk about roles and permissions since they are the main topic of this course.

The rules will be defined in the Policy file we generate specifically for Team management.

php artisan make:policy TeamPolicy

app/Policies/TeamPolicy.php

use App\Models\User;
use App\Enums\Permission;
use Illuminate\Auth\Access\HandlesAuthorization;
 
class TeamPolicy
{
use HandlesAuthorization;
 
public function viewAny(User $user): bool
{
return $user->hasPermissionTo(Permission::LIST_TEAM);
}
 
public function create(User $user): bool
{
return $user->hasPermissionTo(Permission::CREATE_TEAM);
}
}

We use the permission names (Enum again!). We have already assigned the roles for those permissions in the seeders.

Laravel will automatically detect the Policy by the Model, so we can use those Policy checks immediately in our new Controller, with Gate::authorize() in each method.

php artisan make:controller TeamController

We will add three methods inside:

app/Http/Controllers/TeamController.php

use App\Models\Team;
use Illuminate\Support\Facades\Gate;
 
class TeamController extends Controller
{
public function index(): View
{
Gate::authorize('viewAny', Team::class);
 
// Coming soon.
}
 
public function create(): View
{
Gate::authorize('create', Team::class);
 
// Coming soon.
}
 
public function store(StoreTeamRequest $request): RedirectResponse
{
Gate::authorize('create', Team::class);
 
// Coming soon.
}
}

Notice: It's a personal preference whether to use Policies or check the Permissions directly in the Controller. For this relatively simple check, Policies are NOT necessary. You could check this directly in the Controller:

public function index(): View
{
Gate::authorize(Permission::LIST_TEAM);

However, in this project, we decided to go with Policies because...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (31 h 16 min)

You also get:

55 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

S
Sane ✓ Link copied!

I am stuck on "Listing the teams is easy." part.

I created the index blade, and am logged in as the "Master Admin", I have the gate created properly and even did php artisan permission:cache-reset. but I still get 403 when trying to navigate to the /teams page directly, and it does not appear on the navigation bar like your picture showed.

JP
jignal patel ✓ Link copied!

**I'm facing the same issue as well. **

PK
Povilas Korop ✓ Link copied!

Sorry, we noticed only now that there's an important part of the lesson missing. Now added the section about setting the team ID in the session.

M
marli ✓ Link copied!

I need help with spatie teams... If teams is activated in the settings, the @can(\App\Enums\Permission::CREATE_TEAM) does not work. Only when teams are deactivated in the config, then the @can function works. Any ideas?

M
Modestas ✓ Link copied!

With the teams - you need to create the permissions for each of the teams. This means that you will have a lot of duplicated permissions, but they will be for each team.

You can read the documentation here: https://spatie.be/docs/laravel-permission/v6/basic-usage/teams-permissions to see how it's done with teams specifically

M
M ✓ Link copied!

How would I go about showing the total number of users in each team on the teams.index page? I found a way but it's not pretty!

M
Modestas ✓ Link copied!

You can use:

Team::withCount('users')->get()

This will automatically load users_count for each of the team with the amount of users in it

M
M ✓ Link copied!

I had tried it but it gave me a number much higher than the total users.

Here's what I found: "withCount('users')" creates a query containing "COUNT(*)" when a "COUNT(DISTINCT(id))" is needed, so I got around this by using this snippet:

->withCount(['users AS users_count' => function($query) {
      $query->select(DB::raw('count(distinct(model_has_roles.model_id))'));
}])

In App/Models/Team:

    public function users(): MorphToMany
    {
        return $this->morphedByMany(
            User::class,
            'model',
            config('permission.table_names.model_has_roles'),
            'team_id',
            config('permission.column_names.model_morph_key')
        );
    }

Source

M
Modestas ✓ Link copied!

If this happens to you - your users have been assigned the same role multiple times. Please check if there are no model_id with the same role_id assigned to it multiple times.

This can happen if you use ->attach($role) multiple times instead of ->sync($allUserRoles)