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.