filament的多租户方案适合什么样的场景,跟tenancy的多租户方案有什么区别?

这是一个非常好的问题,它触及了现代 Laravel 应用架构中两个不同层次的概念。简单来说:

  • ​Filament 的多租户​​ 是一个​​应用层​​的功能,专注于在同一个应用实例内为不同用户组​​隔离和展示数据​​。
  • ​Tenancy 的多租户​​ 是一个​​架构层​​的方案,专注于在基础设施层面​​完全隔离不同客户​​的数据、代码甚至文件。

它们解决的是完全不同的问题,并且​​不仅可以共存,而且经常是绝佳的搭配​​。 为了让你一目了然,我准备了一个对比表格:

特性Filament (应用层多租户)Tenancy (架构层多租户 / SaaS)
​核心目标​​数据隔离与视图权限控制​​为客户提供完全独立、隔离的应用实例​
​隔离级别​​数据行级​​ (通过 tenant_id)​数据库级、文件级、缓存级​​ (完全隔离)
​技术实现​在业务模型中应用 BelongsToTenant创建独立的数据库、存储路径,并动态切换
​典型场景​公司内部分权给不同部门/团队为外部不同公司提供独立的SaaS服务
​用户感知​使用同一个网址,看到不同的数据看板拥有各自的子域名(如 client1.app.com),感觉像独立应用
​开发复杂度​低至中中至高
​安全性​高 (依赖代码逻辑正确)极高 (物理级别隔离)
​成本与维护​低 (单一数据库,易于备份维护)高 (数据库数量随客户增长,维护更复杂)
​适合客户​公司内部的团队、部门外部的企业客户

Filament 多租户的适用场景 (Scoped Multi-tenancy)

Filament 的方案非常适合​​单个组织内部​​的使用场景,其核心是​​数据权限管理​​而非创建独立产品。 ​​典型用例:​

  • ​公司内部的ERP/CRM系统​​:总公司管理员可以看到所有分公司的数据,而各分公司经理只能查看和操作自己分公司的数据。所有用户都登录到 app.company.com
  • ​SaaS 应用中的“团队”或“项目”功能​​:例如 Notion 或 Linear,你加入一个“工作区”或“团队”后,只能看到该团队内的文档或任务。所有数据都存放在一个数据库中,通过 team_id区分。
  • ​学校管理系统​​:校领导可以看到所有班级数据,而各班老师只能管理自己班级的学生和成绩。

​在 Filament 中的实现方式:​​ 就是在你的 Eloquent 模型和 Filament 资源中使用 ScopedToTenanttrait 并定义关系。

// 1. 在模型中定义与租户(如团队)的关系
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model
{
    public function team(): BelongsTo
    {
        return $this->belongsTo(Team::class);
    }
}

// 2. 在Filament资源中应用Scope
use Filament\Resources\Resource;

class PostResource extends Resource
{
    // 这个Trait会自动过滤当前用户所属团队的数据
    use HasScopedTenant;

    public static function getTenantRelationship(): BelongsTo
    {
        return static::getModel()::team();
    }

    public static function getTenantOwnershipRelationship(\Illuminate\Database\Eloquent\Model $tenant): BelongsTo
    {
        return static::getModel()::team();
    }
}

Tenancy 多租户的适用场景 (SaaS Multi-tenancy)

Tenancy 的方案旨在构建一个​​真正的多租户SaaS平台​​,每个客户都感觉自己在使用一个独立的应用。 ​​典型用例:​

  • ​标准的B2B SaaS产品​​:例如 Shopify、Intercom。你注册后,会获得 yourstore.mysaas.com这样的子域名和一个完全独立的环境,其他客户的存在对你而言是不可见的。
  • ​需要为客户提供高度定制化服务的平台​​:例如,为不同客户启用不同的功能模块,或者允许他们安装自己的自定义插件。
  • ​对数据隔离和安全性有极端要求的行业​​:例如金融、医疗领域的应用,法规要求客户数据必须物理隔离。

​实现方式(以 stancl/tenancy为例):​​ 这涉及到路由、数据库连接和文件存储的动态配置。

# routes/tenant.php
Route::middleware([
    'web',
    InitializeTenancyByDomain::class, // 关键中间件:根据域名初始化租户
    PreventAccessFromCentralDomains::class,
])->group(function () {
    Route::get('/', function () {
        // 这个 '/' 对于不同租户是不同的环境
        return view('welcome');
    });
    // 你的租户路由
});

如何结合使用?(Recommended Architecture)

这两种方案非但不冲突,结合起来反而能构建出强大且灵活的系统。 ​​经典架构:​​ ​​使用 Tenancy 为每个客户创建一个独立的 SaaS 实例,然后在每个实例内部使用 Filament 的多租户功能来管理该客户内部的团队和权限。​​ ​​举例说明:​​ 假设你开发了一个名为 ​​“CloudCRM”​​ 的SaaS产品。

  1. ​第一层隔离 (Tenancy)​​:
    • 你的客户 ​​“公司A”​​ 注册后,获得子域名 companya.cloudcrm.com和一个独立的数据库。
    • 你的客户 ​​“公司B”​​ 注册后,获得子域名 companyb.cloudcrm.com和另一个独立的数据库。
    • ​公司A​​ 和 ​​公司B​​ 的数据完全隔离,互不可见。
  2. ​第二层隔离 (Filament)​​:
    • ​公司A​​ 的老板登录到 companya.cloudcrm.com后,可以创建多个“团队”,例如“销售部”和“市场部”。
    • 他使用 ​​Filament 的管理后台​​ 分配权限:销售团队经理只能看到销售相关的客户和订单,市场团队亦然。
    • 这一切都发生在 ​​公司A​​ 自己的独立数据库内。

总结与选择建议

  • ​如果你的用户属于同一个组织​​(例如公司、学校的内部用户),你只是想​​在他们之间分配数据查看和操作的权限​​,那么只使用 ​​Filament 的多租户​​ 就足够了。它简单、高效、易于维护。
  • ​如果你是在构建一个面向外部不同企业客户的SaaS产品​​,那么你需要使用 ​​Tenancy​​ 来为他们提供真正隔离的实例。在此基础上,你可以在每个客户实例内部使用 ​​Filament 的多租户​​ 来管理该客户内部的用户权限。
  • ​绝大多数情况下,Filament 的多租户是其作为Admin面板的“内部功能”,而Tenancy是构建整个应用的“底层架构”​​。它们处于不同层级,协同工作。

Comments

No comments yet. Why don’t you start the discussion?

发表回复