Courses

Laravel 11 Multi-Tenancy: All You Need To Know

Setting user_id Column Automatically: Two Ways

We start our course with a simple version of multi-tenancy: records restricted by users assigned to them, so users would see only their records.

Some people don't even consider it a "multi-tenancy", meaning records should be restricted not by a user, but by company or team, using sub-domains, multi-databases, or something more complex.

But, in a broader sense, multi-tenancy means dividing your data by some tenant, however you define that tenant in your project. So, as the most simple example, we will divide the data of Project and Task Eloquent models by projects.user_id and tasks.user_id fields, in the same database.


I have made a simple demo project with two Models: Task and Project with CRUDs for both of them. Also, I added a relation: Task -> belongsTo -> Project.

NOTE: The source code for Model, Migrations, and CRUD can be found on GitHub.

In this section of the course, we will cover how to create a user_id field and filter by that so every user would see only their projects and tasks.

First, we must add a user_id column to the projects table.

php artisan make:migration "add user id to projects table"

database/migrations/xxx_add_user_id_to_projects_table.php:

Schema::table('projects', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});

We also added the user_id to the Project model in the fillable. I prefer to have all the fields fillable except for id and timestamps.

app/Models/Project.php:

class Project extends Model
{
protected $fillable = [
'name',
'user_id',
];
}

Now, our goal is to add user_id value to the projects automatically, from the logged-in user. And we have two options here.


Option 1. Controller.

In the store() method of the ProjectController, we create the record with $request->validated(). The validated request comes from the Form Request class. So, the first way to add user_id is to add it alongside the validated request.

app/Http/Controllers/ProjectController.php:

class ProjectController extends Controller
{
// ...
 
public function store(StoreProjectRequest $request)
{
Project::create($request->validated()
+ ['user_id' => auth()->id()]
);
 
return redirect()->route('projects.index');
}
 
// ...
}

Now, if we add a new project to the database, we can see that the user was assigned to a project.

But the problem is that new Project may come not from that Controller only. It may be from some Queued Job, Terminal command, Artisan command, or some API. So we should set the user_id automatically wherever that project creation is coming from. So...


Option 2. Model: creating()

A better way would be to assign user_id to the Model when the record is being created. Typically, this should be done using the booted() method of the Model by calling the creating event.

app/Models/Project.php:

class Project extends Model
{
protected $fillable = [
'name',
'user_id',
];
 
protected static function booted(): void
{
static::creating(function (Project $project) {
$project->user_id = auth()->id();
});
}
}

After adding a second project, we can see in the database the result is the same: the project has a user.

Another almost identical option would be to use Eloquent Observers and create the creating() method in the Observer, instead of the Model. But it's a personal preference.


So, we have set our user_id field. Now, how do you filter by that field everywhere, wherever you need projects or tasks? We will discuss a few ways in the following lessons.

No comments or questions yet...