Pages

Thursday, April 3, 2025

Complete Guide to Integrating Tenancy for Laravel v3

Complete Guide to Integrating Tenancy for Laravel v3

Complete Guide to Integrating Tenancy for Laravel v3

Multi-tenancy is a crucial requirement for many modern SaaS applications. The Tenancy for Laravel package (formerly known as hyn/multi-tenant) provides an elegant solution for implementing multi-tenancy in Laravel applications. This guide will walk you through the complete integration process for version 3 of the package.

Prerequisites

  • Laravel 8.x or higher
  • PHP 8.0 or higher
  • Composer installed
  • Database server (MySQL, PostgreSQL, SQLite, or SQL Server)

Step 1: Installation

First, install the package via Composer:

composer require stancl/tenancy

Then, publish the configuration file:

php artisan vendor:publish --provider="Stancl\Tenancy\TenancyServiceProvider" --tag=config
Note: The package was previously known as hyn/multi-tenant. If you're migrating from v2, check the upgrade guide.

Step 2: Database Configuration

Tenancy v3 uses a central database for tenant metadata and separate databases for each tenant. Configure your central database connection in .env:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=central_database
DB_USERNAME=root
DB_PASSWORD=

Configure the tenancy settings in config/tenancy.php:

'database' => [
    'based_on' => 'mysql', // The connection to use as a base for tenant databases
    'prefix' => 'tenant_',
    'suffix' => '',
],

Step 3: Setting Up Tenants

Run the migrations to create the tenants table:

php artisan tenancy:install

Then migrate:

php artisan migrate

Create a Tenant model and migration:

php artisan make:model Tenant -m

Update the migration:

Schema::create('tenants', function (Blueprint $table) {
    $table->string('id')->primary();
    
    // Your custom columns
    $table->string('name');
    $table->string('domain')->unique();
    $table->json('data')->nullable();
    
    $table->timestamps();
});

Step 4: Configuring Routes

Update your routes/web.php to handle tenant routes:

Route::middleware([
    'web',
    InitializeTenancyByDomain::class,
    PreventAccessFromCentralDomains::class,
])->group(function () {
    // Your tenant routes here
    Route::get('/', function () {
        return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
    });
});

// Central domain routes
Route::get('/', function () {
    return 'This is the central domain.';
});

Step 5: Tenant Identification

Configure how tenants are identified in config/tenancy.php:

'tenant_model' => \App\Models\Tenant::class,

'identification_middleware' => [
    InitializeTenancyByDomain::class,
    // Or InitializeTenancyBySubdomain::class,
    // Or InitializeTenancyByPath::class,
],

Step 6: Creating Tenants

Create a tenant programmatically:

$tenant = Tenant::create([
    'id' => 'acme',
    'name' => 'ACME Corp',
    'domain' => 'acme.yourdomain.com',
]);

$tenant->domains()->create([
    'domain' => 'acme.yourdomain.com',
]);
Note: The package will automatically create a database for the tenant when you create the tenant record.

Step 7: Running Tenant-Specific Commands

You can run artisan commands for specific tenants:

php artisan tenancy:run migrate --tenant=acme

Or for all tenants:

php artisan tenancy:run migrate --all

Step 8: Storage Configuration

Configure tenant-specific storage in config/filesystems.php:

'tenant' => [
    'driver' => 'local',
    'root' => storage_path('app/tenant/' . tenant('id')),
],

Step 9: Cache Configuration

Configure tenant-specific cache in config/cache.php:

'tenant' => [
    'driver' => 'database',
    'table' => 'tenant_cache',
    'connection' => 'tenant',
],

Step 10: Queue Configuration

For tenant-aware queues, update your queue configuration:

'connections' => [
    'tenant' => [
        'driver' => 'database',
        'table' => 'jobs',
        'queue' => 'default',
        'retry_after' => 90,
        'after_commit' => false,
    ],
],

Advanced Features

Tenant Assets

Serve tenant-specific assets:

Route::get('/assets/{path}', function ($path) {
    return response()->file(storage_path("app/tenant/" . tenant('id') . "/assets/$path"));
})->where('path', '.*');

Custom Tenant Database Creation

Override the default database creation logic:

Event::listen(TenantCreated::class, function (TenantCreated $event) {
    $event->tenant->run(function () {
        // Custom database setup
        Artisan::call('migrate', [
            '--path' => 'database/migrations/tenant',
            '--force' => true,
        ]);
        
        // Seed data
        Artisan::call('db:seed', [
            '--class' => 'TenantDatabaseSeeder',
        ]);
    });
});

Central Domain Access to Tenant Data

Access tenant data from the central domain:

tenancy()->initialize('tenant-id');
// Now you can access tenant data
tenancy()->end();

Troubleshooting

Common Issues:
  • Make sure your tenant domains are properly configured in your hosts file or DNS
  • Check that your database user has permissions to create databases
  • Verify that your cache and session drivers are tenant-aware
  • Ensure all necessary middleware is applied to your routes

Conclusion

Tenancy for Laravel v3 provides a powerful and flexible solution for implementing multi-tenancy in your Laravel applications. By following this guide, you've set up a robust multi-tenant architecture that can scale with your application's needs.

For more advanced features and customization options, refer to the official documentation.

No comments:

Post a Comment

Fiverr Fee Calculator – Know What You Really Earn or Pay!

Fiverr Fee Calculator – Know What You Really Earn or Pay! 💸 "How much will I actually earn after Fiverr takes its cut?...