从0到1构建多租户SaaS平台:LaravelTenancy实战指南

从0到1构建多租户SaaS平台:LaravelTenancy实战指南

【免费下载链接】laravel Laravel 是一个具有表现力和优雅语法的 web 应用程序框架。我们已经为您下一个重大创意奠定了基础,让您无需在琐碎细节上花费过多精力,可以专注于创造性的开发工作。 【免费下载链接】laravel 项目地址: https://gitcode.com/GitHub_Trending/la/laravel

你是否正在为如何用Laravel快速开发支持多客户的SaaS系统而烦恼?是否在数据隔离、租户路由、权限控制等问题上反复踩坑?本文将通过5个实战步骤,带你从零构建一个企业级多租户应用,解决90%的常见痛点。读完本文你将掌握:

  • 三种租户隔离方案的选型决策
  • Stancl/Tenancy扩展的无缝集成
  • 自动化租户迁移与数据隔离实现
  • 多租户路由与中间件配置
  • 生产环境部署的关键安全配置

多租户架构选型:3种方案优缺点对比

在开始编码前,需根据业务需求选择合适的租户隔离策略。Laravel生态中主流方案有三种:

方案实现方式优势劣势适用场景
独立数据库为每个租户创建独立数据库最高级别隔离,性能最优维护成本高,备份复杂金融、医疗等高合规要求场景
共享数据库独立Schema同一数据库不同表前缀中等隔离,运维简单跨租户查询复杂中小型SaaS应用
共享数据库共享表所有租户数据在同一表,通过tenant_id区分部署简单,资源占用低隔离性差,性能瓶颈轻量级应用或原型验证

推荐选择:中小团队优先选择"共享数据库独立Schema"方案,平衡开发效率与数据安全。本文将基于此方案展开实现,使用Stancl/Tenancy扩展(需通过composer require stancl/tenancy安装)。

扩展集成与配置初始化

安装核心依赖

由于当前环境未检测到Composer,实际部署时需先执行:

composer require stancl/tenancy:^3.7

配置服务提供者

修改app/Providers/AppServiceProvider.php,注册租户服务:

public function register()
{
    $this->app->register(\Stancl\Tenancy\TenancyServiceProvider::class);
    $this->app->register(\Stancl\Tenancy\Providers\ConsoleServiceProvider::class);
}

生成配置文件

php artisan tenancy:install

该命令会自动创建config/tenancy.php配置文件,关键配置项说明:

// 租户识别方式:域名/子目录/请求头
'tenant_identification' => [
    'driver' => 'domain', // 推荐生产环境使用域名识别
    'prefix' => 'tenant-', // 数据库Schema前缀
],

// 租户数据连接
'database' => [
    'connection' => 'tenant', // 对应config/database.php中的连接配置
    'prefix_base' => 'tenant_', // Schema名称前缀
],

数据模型与迁移设计

创建租户模型

新建app/Models/Tenant.php:

use Stancl\Tenancy\Database\Models\Tenant as BaseTenant;
use Stancl\Tenancy\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\Concerns\HasDatabase;
use Stancl\Tenancy\Database\Concerns\HasDomains;

class Tenant extends BaseTenant implements TenantWithDatabase
{
    use HasDatabase, HasDomains;
    
    protected $fillable = [
        'id', 'name', 'plan', // 可扩展租户属性:名称、订阅计划等
    ];
}

多租户迁移策略

  1. 系统级迁移:保留原有的database/migrations/目录,用于创建租户表、系统配置表等全局数据

  2. 租户级迁移:创建database/migrations/tenant/目录,存放租户专属表结构:

mkdir -p database/migrations/tenant
php artisan make:migration create_tenant_users_table --path=database/migrations/tenant

修改租户迁移文件,添加租户隔离字段:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

路由与中间件配置

配置多租户路由

修改routes/web.php,区分系统路由与租户路由:

// 系统路由:租户注册、登录等
Route::get('/register-tenant', [TenantController::class, 'create']);
Route::post('/register-tenant', [TenantController::class, 'store']);

// 租户路由组:需通过租户中间件
Route::middleware([
    \Stancl\Tenancy\Middleware\InitializeTenancyByDomain::class,
    \Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains::class,
])->group(function () {
    Route::get('/', function () {
        return view('tenant.welcome'); // 租户专属视图
    });
    
    Route::get('/dashboard', [TenantDashboardController::class, 'index']);
});

创建租户控制器

新建app/Http/Controllers/TenantController.php:

use App\Models\Tenant;
use Illuminate\Http\Request;

class TenantController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required',
            'domain' => 'required|unique:domains',
            'plan' => 'required|in:basic,premium',
        ]);

        // 创建租户
        $tenant = Tenant::create([
            'id' => Str::random(10), // 生成唯一租户ID
            'name' => $validated['name'],
            'plan' => $validated['plan'],
        ]);

        // 关联域名
        $tenant->domains()->create([
            'domain' => $validated['domain'],
        ]);

        // 运行租户迁移
        $tenant->runMigrations();

        return redirect()->route('tenant.login', $tenant);
    }
}

生产环境安全与性能优化

关键安全配置

  1. 数据库权限控制:在config/database.php中为租户连接配置最小权限账户:
'connections' => [
    'tenant' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST'),
        'database' => null, // 动态指定
        'username' => env('TENANT_DB_USER'), // 仅拥有CREATE SCHEMA权限的账户
        'password' => env('TENANT_DB_PASSWORD'),
    ],
],
  1. 文件存储隔离:修改config/filesystems.php添加租户磁盘:
'disks' => [
    'tenant' => [
        'driver' => 'local',
        'root' => storage_path('app/tenants'),
        'url' => env('APP_URL').'/storage/tenants',
        'visibility' => 'public',
    ],
],

性能优化建议

  1. 缓存租户配置:在app/Providers/AppServiceProvider.php中添加:
public function boot()
{
    if (tenancy()->initialized) {
        Cache::store('redis')->rememberForever(
            'tenant:'.$tenant->id.':config',
            fn () => $tenant->config
        );
    }
}
  1. 队列任务隔离:使用租户ID作为队列名称前缀,修改config/queue.php
'default' => tenancy()->initialized ? 'tenant_'.tenant('id') : 'default',

总结与进阶方向

通过本文实现的多租户架构,已具备企业级SaaS平台的核心能力:完整的数据隔离、独立的租户域名、自动化迁移管理。后续可扩展以下高级特性:

  • 基于app/Models/User.php实现跨租户用户权限管理
  • 集成Stripe实现租户订阅计费系统
  • 使用Redis实现租户级缓存与限流

建议通过tests/Feature/TenancyTest.php编写自动化测试,确保多租户功能稳定性:

public function test_tenant_data_is_isolated()
{
    $tenant1 = Tenant::factory()->create();
    $tenant2 = Tenant::factory()->create();

    tenancy()->initialize($tenant1);
    User::create(['name' => 'Tenant 1 User']);

    tenancy()->initialize($tenant2);
    $this->assertCount(0, User::all()); // 验证数据隔离
}

完整代码结构可参考项目README.md中的多租户章节,建议配合Laravel Telescope进行租户请求调试与监控。

【免费下载链接】laravel Laravel 是一个具有表现力和优雅语法的 web 应用程序框架。我们已经为您下一个重大创意奠定了基础,让您无需在琐碎细节上花费过多精力,可以专注于创造性的开发工作。 【免费下载链接】laravel 项目地址: https://gitcode.com/GitHub_Trending/la/laravel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值