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. 性能优化方案
- 连接池:数据库连接复用
- 租户缓存:常用数据预加载
- 路由缓存:加速租户路由解析
- 数据分片:大租户独立部署