magetech/laravel-saas-tenancy

Multi-tenant architecture for Laravel SaaS applications — shared database or database-per-tenant with zero code changes to switch strategies.

Maintainers

Package info

github.com/magetechsol/laravel-saas-tenancy

pkg:composer/magetech/laravel-saas-tenancy

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-08-25 13:18 UTC

This package is not auto-updated.

Last update: 2026-08-25 19:46:58 UTC


README

Multi-tenant SaaS infrastructure for Laravel with tenant isolation, user management, and middleware support.

Features

  • Multi-tenant Architecture — Shared database or database-per-tenant strategies
  • Tenant Identification — Subdomain, path, header, session, or cookie resolvers
  • User Management — Tenant-scoped users with roles (owner, admin, member, viewer)
  • Middleware Stack — IdentifyTenant, InitializeTenancy, PreventTenantMixing
  • Query Scoping — Auto-scope Eloquent queries by tenant
  • Activity Logging — Track tenant events (created, activated, suspended, deleted)
  • Package Tool — CLI commands for tenant management

Requirements

  • PHP 8.3+
  • Laravel 11.x, 12.x, or 13.x
  • magepackages/package-toolkit (auto-installed)

Installation

composer require magepackages/laravel-saas-tenancy
php artisan mts:saas:install

Quick Start

1. Run Migrations

php artisan migrate

2. Create a Tenant

php artisan mts:saas:create-tenant "Acme Corp"

3. Identify Tenants

use MageTech\SaaS\Support\Facades\Tenant;

// Identify current tenant
Tenant::identify();

// Get current tenant
$tenant = Tenant::getTenant();

// Create a tenant
$tenant = Tenant::create(['name' => 'Acme', 'slug' => 'acme']);

4. Use Models

use MageTech\SaaS\Models\Tenant;
use MageTech\SaaS\Models\TenantUser;

// Get tenant users
$users = TenantUser::forTenant($tenant->id)->get();

// Check role
if ($tenantUser->isAdmin()) {
    // ...
}

5. Scoping Queries

use MageTech\SaaS\Concerns\BelongsToTenant;

class Order extends Model
{
    use BelongsToTenant;
}

// Auto-scoped to current tenant
$orders = Order::all();

// Without scope
$allOrders = Order::withoutGlobalScope(TenantScope::class)->get();

Configuration

Config is published to config/mts-saas.php:

return [
    'strategy' => 'shared', // 'shared' or 'database'
    'key_type' => 'uuid',   // 'uuid', 'ulid', or 'int'
    'resolvers' => [
        'subdomain' => ['enabled' => true],
        'path' => ['enabled' => false],
        // ...
    ],
];

Resolvers

Resolver Description
Subdomain Extracts tenant from acme.example.com
Domain Maps domain to tenant
Path Extracts tenant from URL /acme/...
Header Reads X-Tenant-ID header
Session Reads tenant from session
Cookie Reads tenant from cookie

Events

  • TenantCreated — Fired when a tenant is created
  • TenantActivated — Fired when a tenant is activated
  • TenantSuspended — Fired when a tenant is suspended
  • TenantDeleted — Fired when a tenant is deleted
  • TenantIdentified — Fired when a tenant is identified
  • TenantDatabaseReady — Fired when tenant database is ready

License

MIT License