ThinkPHP6企业级实战:构建智能多租户SaaS平台
一、系统架构设计
租户识别 → 动态配置 → 数据隔离 → 路由分发 → 服务共享
二、核心功能实现
1. 租户识别中间件
namespace appmiddleware;
class TenantIdentify
{
public function handle($request, Closure $next)
{
// 从子域名识别租户
$subDomain = explode('.', $request->host())[0];
// 从数据库验证租户
$tenant = appmodelTenant::where('domain', $subDomain)->find();
if (!$tenant) {
return json(['code' => 404, 'msg' => '租户不存在']);
}
// 设置租户上下文
appcommonTenantContext::setTenant($tenant);
return $next($request);
}
}
2. 动态数据库切换
namespace appcommon;
class TenantDatabase
{
public static function switch($tenant)
{
// 每个租户独立数据库
$config = [
'type' => 'mysql',
'hostname' => '127.0.0.1',
'database' => 'tenant_' . $tenant->id,
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
];
// 动态修改配置
thinkfacadeDb::connect($config);
}
}
3. 数据范围控制
namespace appmodel;
use thinkModel;
class BaseModel extends Model
{
protected function scopeTenant($query)
{
$tenantId = appcommonTenantContext::getTenantId();
$query->where('tenant_id', $tenantId);
}
}
// 使用示例
class Product extends BaseModel
{
// 自动应用租户范围
public static function onBeforeQuery($query)
{
$query->tenant();
}
}
三、高级功能实现
1. 租户路由优化
// route/tenant.php
Route::domain(':subdomain', function() {
Route::get('/', 'index/hello');
Route::resource('product', 'Product');
Route::resource('order', 'Order');
})->middleware(TenantIdentify::class);
// 动态注册租户路由
$tenants = appmodelTenant::select();
foreach ($tenants as $tenant) {
Route::domain($tenant->domain . '.saas.com', function() use ($tenant) {
// 租户自定义路由
});
}
2. 共享数据缓存隔离
namespace appcommon;
class TenantCache
{
public static function get($name)
{
$tenantId = TenantContext::getTenantId();
return thinkfacadeCache::get($tenantId . '_' . $name);
}
public static function set($name, $value, $expire = null)
{
$tenantId = TenantContext::getTenantId();
thinkfacadeCache::set($tenantId . '_' . $name, $value, $expire);
}
}
四、实战案例演示
1. 租户管理后台
namespace appcontrolleradmin;
class Tenant extends Base
{
public function create()
{
$data = request()->post();
// 创建租户数据库
$this->createTenantDatabase($data['database']);
// 初始化基础数据
$this->initTenantData($data);
return json(['code' => 200, 'msg' => '创建成功']);
}
private function createTenantDatabase($dbName)
{
$sql = "CREATE DATABASE IF NOT EXISTS `{$dbName}` DEFAULT CHARACTER SET utf8mb4";
Db::execute($sql);
}
}
2. 性能优化方案
- 连接池:数据库连接复用
- 租户缓存:常用数据预加载
- 路由缓存:加速租户路由解析
- 数据分片:大租户独立部署

