Back to Course |
Laravel 11 Multi-Tenancy: All You Need To Know

Making DB Structure Changes for Tenants

In this course, we have covered all the basic features and all the primary use cases for packages for multi-tenancy. Let's spend some time on advanced features or what else we can do after installing the stancl/tenancy package.

Based on the demo project, I will continue working on that for upcoming lessons and will introduce a few more features and show how it works in a bit advanced way.

In this lesson, what do you do if you want to add something to the database structure of tenants?

For example, you have a task CRUD, and every tenant has its own database, and you want to add a field there. Let's add a description column to the tasks.


The package adds tenant migrations into the database/migrations/tenant folder. Then, instead of running the Artisan command migrate, we must run the tenants:migrate command.

So, first, the Migration.

php artisan make:migration "add description to tasks table" --path=database/migrations/tenant

database/migrations/tenant/xxx_add_description_to_tasks_table.php:

Schema::table('tasks', function (Blueprint $table) {
$table->string('description')->nullable();
});

app/Models/Task.php:

class Task extends Model
{
protected $fillable = [
'name',
'project_id',
'description',
];
 
// ...
}

Then, we add those fields to the create and edit forms.

resources/views/tasks/create.blade.php:

// ...
 
<div class="mt-4">
<x-input-label for="description" :value="__('Description')"/>
 
<x-text-input id="description" class="block mt-1 w-full" type="text" name="description" :value="old('description')" />
 
<x-input-error :messages="$errors->get('description')" class="mt-2" />
</div>
 
// ...

resources/views/tasks/edit.blade.php:

// ...
 
<div class="mt-4">
<x-input-label for="description" :value="__('Description')"/>
 
<x-text-input id="description" class="block mt-1 w-full" type="text" name="description" :value="$task->description" />
 
<x-input-error :messages="$errors->get('description')" class="mt-2" />
</div>
 
// ...

And let's show the description in the table.

resources/views/tasks/index.blade.php:

// ...
 
<th scope="col" class="px-6 py-3 text-left">
Description
</th>
 
// ...
 
<td class="px-6 py-4 font-medium text-gray-900 dark:text-white whitespace-nowrap">
{{ $task->description }}
</td>
// ...

We must add a description column to the Form Request.

app/Http/Requests/StoreTaskRequest.php:

class StoreTaskRequest extends FormRequest
{
// ...
 
public function rules(): array
{
return [
'name' => 'required',
'project_id' => 'required',
'description' => 'nullable|string',
];
}
}

app/Http/Requests/UpdateTaskRequest.php:

class UpdateTaskRequest extends FormRequest
{
// ...
 
public function rules(): array
{
return [
'name' => 'required',
'project_id' => 'required',
'description' => 'nullable|string',
];
}
}

If we tried to add a description, we would receive an error Unknown column 'description'... because we haven't run the migrations yet.

However, we must run migrations to each tenant's database. Instead of a regular Artisan command migrate, now we must use the command provided by the package tenants:migrate. This command will run all the migrations from a database/migrations/tenant folder.

When running the tenants:migrate command, we can see in the output migrations are run to each tenant.

Now, we can add and edit descriptions for a task.


This is how you can make any changes to your database structure for all the tenants. You generate the migration in the tenant subfolder and then run the tenants:migrate Artisan command to process the changes into all tenants.

You can find the source code for this lesson on GitHub.