0

0

如何优雅地解决Laravel单数据库多租户数据隔离问题?使用nunomazer/laravel-samehouse轻而易举!

DDD

DDD

发布时间:2025-11-05 12:53:02

|

905人浏览过

|

来源于php中文网

原创

如何优雅地解决laravel单数据库多租户数据隔离问题?使用nunomazer/laravel-samehouse轻而易举!

你是否正在构建一个SaaS平台,为不同的客户提供服务,但又希望所有客户的数据都存储在同一个数据库中,以降低运维成本和复杂性?这种单数据库多租户的架构模式虽然高效,却也带来了巨大的挑战:如何确保不同租户之间的数据严格隔离,避免用户看到或修改不属于自己的信息?手动在每一个数据库查询中添加 WHERE tenant_id = current_tenant_id 这样的条件,不仅工作量巨大,容易遗漏导致数据安全隐患,而且会使代码变得臃肿不堪,难以维护。

幸运的是,PHP社区的Composer生态为我们提供了强大的解决方案。今天,我将向你介绍一个能够彻底解决这个痛点的Composer包:nunomazer/laravel-samehouse。它能让你在Laravel应用中实现优雅、自动化的单数据库多租户数据隔离。

Composer在线学习地址:学习地址

为什么选择 nunomazer/laravel-samehouse

nunomazer/laravel-samehouse 是一个基于 HipsterJazzbo/LandlordTorzer/awesome-landlord 改进而来的Laravel/Lumen包,专注于实现单数据库多租户。它的核心理念是:通过自动化的全局作用域(Global Scopes),确保所有针对租户模型的查询都只返回当前租户的数据。这意味着你无需在每个Eloquent查询中手动添加租户ID,大大简化了开发工作。

安装与配置:让魔法开始

首先,使用Composer将 nunomazer/laravel-samehouse 添加到你的项目中:

composer require nunomazer/laravel-samehouse

对于 Laravel 项目:

config/app.php 中注册 ServiceProvider:

    'providers' => [
        // ...
        NunoMazer\Samehouse\LandlordServiceProvider::class,
    ],

如果你喜欢使用 Facade,也可以注册:

    'aliases' => [
        // ...
        'Landlord'   => NunoMazer\Samehouse\Facades\Landlord::class,
    ],

为了更好地控制,你可以发布其配置文件

php artisan vendor:publish --provider="NunoMazer\Samehouse\LandlordServiceProvider"

发布后,你可以在 config/landlord.php 中设置 default_tenant_columns,这对于那些没有明确指定 $tenantColumns 属性的模型非常有用。

对于 Lumen 项目:

bootstrap/app.php 中注册 ServiceProvider,并确保启用了Eloquent:

$app->register(NunoMazer\Samehouse\LandlordServiceProvider::class);
$app->withEloquent(); // 确保这一行没有被注释掉

核心用法:定义租户上下文

nunomazer/laravel-samehouse 的一个关键点是:它无状态。这意味着你需要在每个请求中明确告知它当前是哪个租户在操作。最常见和推荐的做法是使用中间件(Middleware)。

假设你的用户表(users)中有一个 company_id 字段,用于关联用户所属的公司(租户)。你可以创建一个 SetTenant 中间件:

php artisan make:middleware SetTenant

然后,编辑 app/Http/Middleware/SetTenant.php 文件:

check() && auth()->user()->company_id) {
            // 将当前请求的租户设置为认证用户的 company_id
            Landlord::addTenant('company_id', auth()->user()->company_id);
        }

        return $next($request);
    }
}

最后,将这个中间件添加到 app/Http/Kernel.php 中的 webapi 中间件组,或者添加到特定的路由中:

// app/Http/Kernel.php
protected $middlewareGroups = [
    'web' => [
        // ...
        \App\Http\Middleware\SetTenant::class, // 添加到这里
    ],

    'api' => [
        // ...
        \App\Http\Middleware\SetTenant::class, // 或者添加到这里
    ],
];

通过这种方式,在每个请求开始时,Landlord 就会知道当前操作的租户ID,并将其应用到后续的所有数据库查询中。

你也可以通过 Landlord::removeTenant('company_id') 来移除当前租户上下文,或者使用 Landlord::hasTenant('company_id') 检查某个租户是否已被设置。

Bandy AI
Bandy AI

全球领先的电商设计Agent

下载

模型关联:自动数据隔离的魔法

要让你的Eloquent模型支持租户隔离,只需简单地使用 BelongsToTenants Trait:

现在,当你在 Product 模型上执行任何查询时,nunomazer/laravel-samehouse 都会自动添加 WHERE company_id = [当前租户ID] 条件:

// 假设当前租户的 company_id 是 1
$products = Product::all(); // 相当于 SELECT * FROM products WHERE company_id = 1

$product = Product::find(5); // 相当于 SELECT * FROM products WHERE id = 5 AND company_id = 1

如果 find(5) 对应的产品不属于当前租户,它将抛出 ModelNotFoundForTenantException 异常,而不是 Laravel 默认的 ModelNotFoundException,这有助于你更快地定位问题。

创建新模型时自动填充租户ID:

当你创建新模型实例时,如果 company_id 尚未设置,Landlord 会自动填充:

// 如果当前租户的 company_id 是 1,则会自动设置 product 的 company_id 为 1
$product = Product::create(['name' => '新产品', 'price' => 99.99]);

指定租户列:

如果你的模型使用的租户列名不是 default_tenant_columns 中定义的,或者你需要为特定模型指定不同的租户列,可以在模型中设置 $tenantColumns 属性:

class Order extends Model
{
    use BelongsToTenants;

    public $tenantColumns = ['client_id']; // 为 Order 模型指定租户列为 client_id
    // ...
}

进阶用法:打破隔离与临时禁用

有时,你可能需要查看所有租户的数据(例如在管理后台),或者在执行某些特定任务时暂时禁用租户隔离。

查看所有租户数据:

使用 allTenants() 方法可以临时禁用租户作用域:

// 这将返回所有公司的产品,忽略当前租户设置
$allProducts = Product::allTenants()->get();

禁用特定租户作用域:

如果你同时设置了多个租户(例如 company_idbranch_id),但只想禁用其中一个,可以使用 withoutGlobalScope()

// 忽略 company_id 作用域,但其他租户作用域(如果有)依然生效
$products = Product::withoutGlobalScope('company_id')->get();

全局禁用/启用租户管理:

对于一些管理任务,你可能需要完全禁用 Landlord 的租户管理功能,然后再重新启用:

if (Landlord::isEnabled()) {
    Landlord::disable(); // 禁用租户管理
    // 执行一些需要访问所有租户数据的管理任务
    Landlord::enable();  // 重新启用租户管理
}

总结与优势

nunomazer/laravel-samehouse 为 Laravel 单数据库多租户应用提供了一个优雅且高效的解决方案。它的优势显而易见:

  1. 简化开发: 告别在每个查询中手动添加 WHERE 子句的繁琐,让你的业务逻辑更聚焦。
  2. 提升安全性: 自动化的数据隔离机制,大大降低了因开发失误导致数据泄露的风险。
  3. 易于维护: 代码更整洁,逻辑更清晰,新功能开发和现有功能维护都变得更加容易。
  4. 灵活配置: 支持自定义租户列、临时禁用隔离等多种场景,满足不同业务需求。
  5. 单数据库优势: 让你在享受单数据库带来的部署和管理便利的同时,也能确保数据的严格隔离。

如果你正在为Laravel应用的多租户数据隔离问题而烦恼,nunomazer/laravel-samehouse 绝对值得一试。它将帮助你构建出更健壮、更易维护的SaaS应用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

320

2024.04.09

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

278

2024.04.09

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

373

2024.04.09

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

374

2024.04.10

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

86

2025.08.05

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

65

2025.08.05

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

68

2025.08.05

composer是什么插件
composer是什么插件

Composer是一个PHP的依赖管理工具,它可以帮助开发者在PHP项目中管理和安装依赖的库文件。Composer通过一个中央化的存储库来管理所有的依赖库文件,这个存储库包含了各种可用的依赖库的信息和版本信息。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

154

2023.12.25

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

1

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.5万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 6.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号