In this lesson, I want to explain the concept of Tenancy Bootstrappers. It doesn't sound very easy, but I will try to make it clear.
It's the class that takes care of the tenancy in various parts of your application in multiple functionalities, like creating the databases and taking care of the cache and the file system. In this lesson, I want to demonstrate the queue Tenancy Bootstrapper because it's pretty easy.
What problem does it solve? For example, if you add a job to your queue that needs to process some data from the database, which database should it query? The main one or the tenant one? Then which tenant?
By default, the job does not contain that code. It would load just the Tenant
model and try to do something.
If you enable queue bootstrapper, it will add tenant ID to the jobs and process that when processing the job.
By default, queue bootstrapper is enabled.
config/tenancy.php:
return [ // ... 'bootstrappers' => [ Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper::class, Stancl\Tenancy\Bootstrappers\CacheTenancyBootstrapper::class, Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper::class, Stancl\Tenancy\Bootstrappers\QueueTenancyBootstrapper::class, // Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper::class, // Note: phpredis is needed ], // ...];
Let's send an email to the administrator when a project is created. First, we need a Notification class.
php artisan make:notification ProjectCreatedNotification
The notification must implement the ShouldQueue
interface.
app/Notifications/ProjectCreatedNotification.php:
use App\Models\Project;use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Notifications\Messages\MailMessage;use Illuminate\Notifications\Notification; class ProjectCreatedNotification extends Notification implements ShouldQueue{ use Queueable; public function __construct(private readonly Project $project) { // } public function via(object $notifiable): array { return ['mail']; } public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->line("Project has been created: {$this->project->name}") ->line('Thank you for using our application!'); } public function toArray(object $notifiable): array { return [ // ]; }}
Then, we can call this notification in the Controller.
app/Http/Controllers/ProjectController.php:
use Illuminate\Support\Facades\Notification;use App\Notifications\ProjectCreatedNotification; class ProjectController extends Controller{ // ... public function store(StoreProjectRequest $request) { $project = Project::create($request->validated()); Notification::route('mail', 'admin@admin.com') ->notify(new ProjectCreatedNotification($project)); return redirect()->route('projects.index'); } // ...}
Now, after creating a project, a queued job is launched. In the central database jobs
table we can see that job. The content we are interested in is in the payload
column. We can see there is a tenant_id
.
When you run the queue, the job will precisely catch the tenant ID and query that database. The job is processed successfully:
The email is sent:
We can see the project name in the email, although that name wasn't included in the job payload. In the jobs payload, you can only see the Model itself, which is then queried from the correct database.
So, this is how the package helps run queues on different databases.
You can find the source code for this lesson on GitHub.