PHP code example of roberts / laravel-singledb-tenancy

1. Go to this page and download the library: Download roberts/laravel-singledb-tenancy library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

roberts / laravel-singledb-tenancy example snippets


'caching' => [
    'enabled' => env('TENANT_CACHE_ENABLED', true),
    'store' => env('TENANT_CACHE_STORE', 'array'),
    'ttl' => env('TENANT_CACHE_TTL', 3600),
],

'failure_handling' => [
    'unresolved_tenant' => 'fallback', // fallback|continue|exception|redirect
],

use Roberts\LaravelSingledbTenancy\Models\Tenant;

// Create a tenant with a root domain
$tenant = Tenant::create([
    'name' => 'Acme Corporation',
    'domain' => 'acme.com',
    'slug' => 'acme', // Auto-generated if not provided
]);

// Create a tenant with a subdomain
$tenant = Tenant::create([
    'name' => 'Beta Company',
    'domain' => 'beta.acme.com', // Full subdomain in domain field
    'slug' => 'beta',
]);

// Create another tenant with a different subdomain
$tenant = Tenant::create([
    'name' => 'Enterprise Division',
    'domain' => 'enterprise.acme.com', // Each subdomain gets its own entry
    'slug' => 'enterprise',
]);

use Roberts\LaravelSingledbTenancy\Traits\HasTenant;

class Post extends Model
{
    use HasTenant;
    
    protected $fillable = ['tenant_id'];
}

// Domain resolution for all routes
Route::middleware(['web', 'tenant'])->group(function () {
    Route::get('/dashboard', DashboardController::class);
});

// Domain resolution only
Route::middleware(['web', 'tenant:domain'])->group(function () {
    Route::get('/custom', CustomController::class);
});

use Roberts\LaravelSingledbTenancy\Concerns\TenantAware;

class ProcessReport implements ShouldQueue
{
    use TenantAware;

    public function handle()
    {
        // All Eloquent queries are automatically scoped to the correct tenant.
        $sales = Sale::all();
    }
}

use Roberts\LaravelSingledbTenancy\Commands\TenantAwareCommand;

class GenerateReport extends TenantAwareCommand
{
    protected $signature = 'report:generate {--tenant=} {--all-tenants}';
    protected $description = 'Generate a sales report.';

    public function handleTenant()
    {
        $this->info('Generating report for: ' . current_tenant()->name);
    }
}

use Roberts\LaravelSingledbTenancy\Events\TenantCreated;

protected $listen = [
    TenantCreated::class => [
        'App\Listeners\SetupNewTenant',
    ],
];

// Get current tenant
$tenant = current_tenant();
$tenantId = current_tenant_id();

// Check if tenant is set
if (has_tenant()) {
    // Tenant-specific logic
}

// Require tenant (throws exception if none set)
$tenant = 

// Set tenant context
tenant_context()->set($tenant);

// Clear tenant context
tenant_context()->clear();

// Run without tenant context (see all data)
tenant_context()->runWithout(function () {
    $allPosts = Post::all(); // All posts across all tenants
});

// Automatically scoped to current tenant
$posts = Post::all();

// Query specific tenant
$posts = Post::forTenant($tenant)->get();

// Query all tenants (removes tenant scope)
$allPosts = Post::forAllTenants()->get();

// Custom tenant column (override default 'tenant_id')
class CustomModel extends Model
{
    use HasTenant;
    
    protected $tenantColumn = 'organization_id';
}

// routes/tenants/acme.com.php
Route::get('/special', ...);

// Also load all the shared routes

tenant_context()->runWithout(function () {
    $this->assertCount(10, Post::all()); // All tenant data
});

// Root domain resolution
// Request: https://acme.com/dashboard
// Matches: Tenant with domain = 'acme.com'

// Subdomain resolution  
// Request: https://beta.acme.com/dashboard
// Matches: Tenant with domain = 'beta.acme.com'

// Deep subdomain resolution
// Request: https://api.beta.acme.com/dashboard  
// Matches: Tenant with domain = 'api.beta.acme.com'

// Custom domain resolution
// Request: https://customdomain.co.uk/dashboard
// Matches: Tenant with domain = 'customdomain.co.uk'

// Example tenant records:
['id' => 1, 'name' => 'Main Site', 'domain' => 'acme.com', 'slug' => 'main']
['id' => 2, 'name' => 'Beta Site', 'domain' => 'beta.acme.com', 'slug' => 'beta'] 
['id' => 3, 'name' => 'API Site', 'domain' => 'api.acme.com', 'slug' => 'api']
['id' => 4, 'name' => 'Enterprise', 'domain' => 'enterprise.acme.com', 'slug' => 'enterprise']
['id' => 5, 'name' => 'Custom Domain', 'domain' => 'anotherdomain.com', 'slug' => 'another']

use Roberts\LaravelSingledbTenancy\Services\SuperAdmin;

$user = auth()->user();

if (app(SuperAdmin::class)->is($user)) {
    // User is the super admin
}

use Roberts\LaravelSingledbTenancy\Middleware\AuthorizePrimaryTenant;

Route::get('/tenancy-dashboard', ...)->middleware(AuthorizePrimaryTenant::class);

use Roberts\LaravelSingledbTenancy\Models\Tenant;

class PostTest extends TestCase
{
    public function test_posts_are_scoped_to_tenant()
    {
        $tenant1 = Tenant::factory()->create();
        $tenant2 = Tenant::factory()->create();
        
        tenant_context()->set($tenant1);
        $post1 = Post::create(['title' => 'Tenant 1 Post']);
        
        tenant_context()->set($tenant2);
        $post2 = Post::create(['title' => 'Tenant 2 Post']);
        
        // Verify isolation
        tenant_context()->set($tenant1);
        $this->assertCount(1, Post::all());
        $this->assertEquals('Tenant 1 Post', Post::first()->title);
    }
}

// Properties
$tenant->id;           // Primary key
$tenant->name;         // Tenant display name
$tenant->slug;         // URL-safe identifier
$tenant->domain;       // Custom domain (optional)
$tenant->suspended_at; // Soft delete timestamp

// Methods
$tenant->isActive();                    // Check if tenant is active
$tenant->suspend();                     // Suspend tenant
$tenant->reactivate();                  // Reactivate tenant
$tenant->url($path = '/');              // Generate tenant URL
Tenant::resolveByDomain($domain);       // Find tenant by domain
Tenant::resolveBySlug($slug);           // Find tenant by slug

// Set/get current tenant
tenant_context()->set($tenant);
$tenant = tenant_context()->get();
tenant_context()->clear();

// Run code in tenant context
tenant_context()->runWith($tenant, $callback);
tenant_context()->runWithout($callback);

// Check tenant state
tenant_context()->has();
tenant_context()->id();

// Apply to routes
Route::middleware('tenant')->group(...);           // All strategies
Route::middleware('tenant:domain')->group(...);    // Domain only
Route::middleware('tenant:subdomain')->group(...); // Subdomain only



return [
    // Tenant model configuration
    'tenant_model' => \Roberts\LaravelSingledbTenancy\Models\Tenant::class,
    
    // Caching configuration
    'caching' => [
        'enabled' => env('TENANT_CACHE_ENABLED', true),
        'store' => env('TENANT_CACHE_STORE', 'array'),
        'ttl' => env('TENANT_CACHE_TTL', 3600),
    ],
    
    // Error handling
    'failure_handling' => [
        'unresolved_tenant' => 'fallback', // fallback|continue|exception|redirect
        'redirect_route' => 'tenant.select',
    ],
    
    // Development
    'development' => [
        'local_domains' => ['.test', '.local', '.localhost'],
        'force_tenant' => env('FORCE_TENANT_DOMAIN'),
    ],
];

Schema::create('tenants', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('slug')->unique();
    $table->string('domain')->nullable()->unique();
    $table->timestamps();
    $table->softDeletes('suspended_at');
});

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('tenant_id')->constrained();
});
bash
php artisan vendor:publish --tag="laravel-singledb-tenancy-migrations"
php artisan migrate
bash
php artisan vendor:publish --tag="laravel-singledb-tenancy-config"
bash
php artisan tenancy:info
bash
php artisan tenancy:add-tenant-column posts