Laravel Jetstream isn't officially presented as a multi-tenancy package. But looking at the things that we have already done in this course, Jetstream does a similar thing helping us to divide users by teams as one of its features.
The Teams feature includes member management, invitations, roles and permissions, inspecting current teams, and other functions. Let's briefly cover how it works and how Jetstream can help us with multi-tenancy.
Jetstream should only be installed in a new Laravel project. Jetstream offers two frontend stacks: Livewire and Inertia.js. We will be using the Livewire stack. Jetstream can be installed in several ways. One of the ways is to provide options for a Laravel installer.
laravel new tenancy --jet --stack=livewire --teams
After registering, in the navigation we can see a dropdown for managing a team.
In the Team Settings
page, we can change the team's name and invite new members to the team. It's similar to what we have done previously with team invitations.
We can create a new team and switch between teams.
The users
table in the database has a current_team_id
column.
Again, it's very similar to what we have done earlier.
The whole team management and all of that stuff is done partly with Livewire, but you don't have to be familiar with Livewire that much to use Jetstream. You can install Jetstream, use it like it is, add more features, add more menu items in addition to the dashboard route, and then proceed with general Laravel code. This is exactly what we will do next.
We will create the same logic of Tasks and Projects CRUD. repeating the same code we did at the beginning of this course, but inside of Jetstream. I will show you that Jetstream is just a starter kit that can provide team functionality. But then you can write good old Laravel code without Livewire or Inertia.
The logic for creating Project
and Task
is identical to what we have done earlier. The only difference is that instead of current_tenant_id
in the users
table, Jetstream uses current_team_id
.
The whole CRUD code is in the GitHub repository.
Filtering records by team is identical to code in the booted()
method of the Model.
app/Models/Project.php:
use Illuminate\Database\Eloquent\Builder; class Project extends Model{ protected $fillable = [ 'name', 'team_id', ]; protected static function booted(): void { $currentTeamId = auth()->user()->current_team_id; static::creating(function (Project $project) use ($currentTeamId) { $project->team_id = $currentTeamId; }); static::addGlobalScope('project_team_id', function (Builder $builder) use ($currentTeamId) { $builder->where('team_id', $currentTeamId); }); } }
app/Models/Task.php:
use Illuminate\Database\Eloquent\Builder; class Task extends Model{ protected $fillable = [ 'name', ]; protected static function booted(): void { static::addGlobalScope('project_team_id', function (Builder $builder) { $builder->whereRelation('project', 'team_id', auth()->user()->current_team_id); }); } public function project(): BelongsTo { return $this->belongsTo(Project::class); }}
Jetstream could be a big time saver if your project needs teams functionality.
The code for the Jetstream example can be found on GitHub.