当前位置: 首页 > news >正文

php方案 PHP的多租户数据隔离

三种方式分开讲:---一、同库 tenant_id 列+全局 Scope composerrequireilluminate/database illuminate/events<?phprequire'vendor/autoload.php';useIlluminate\Database\Capsule\ManagerasDB;useIlluminate\Database\Eloquent\{Builder,Model,Scope};$capsule=newDB;$capsule->addConnection(['driver'=>'sqlite','database'=>':memory:']);$capsule->setAsGlobal();$capsule->bootEloquent();DB::statement('CREATE TABLE orders (id INT, tenant_id INT, amount INT)');DB::table('orders')->insert([['id'=>1,'tenant_id'=>1,'amount'=>100],['id'=>2,'tenant_id'=>2,'amount'=>200],]);classTenantScopeimplementsScope{publicfunctionapply(Builder$b,Model$m):void{$b->where('tenant_id',$GLOBALS['tenant_id']);}}classOrderextendsModel{public$timestamps=false;protectedstaticfunctionbooted():void{static::addGlobalScope(newTenantScope());static::creating(fn($m)=>$m->tenant_id=$GLOBALS['tenant_id']);}}$GLOBALS['tenant_id']=1;print_r(Order::all()->toArray());// 只出 tenant_id=1 的数据逐行解释:classTenantScopeimplementsScope实现 Scope 接口,这是 Eloquent 的全局查询过滤器协议。publicfunctionapply(Builder$b,Model$m):void{$b->where('tenant_id',$GLOBALS['tenant_id']);}每次查询自动追加WHEREtenant_id=?,不用手写,忘了也不会漏。static::addGlobalScope(newTenantScope());把 Scope 挂到模型上,之后Order::all()Order::find()全部自动带过滤。static::creating(fn($m)=>$m->tenant_id=$GLOBALS['tenant_id']);写入时自动填 tenant_id,防止忘记手动赋值导致数据串库。---二、独立数据库+动态连接切换<?phprequire'vendor/autoload.php';useIlluminate\Database\Capsule\ManagerasDB;$capsule=newDB;$capsule->setAsGlobal();$capsule->bootEloquent();functionswitchTenant(int$tenantId):void{DB::addConnection(['driver'=>'sqlite','database'=>"/data/tenant_{$tenantId}.db",],"tenant_{$tenantId}");DB::setDefaultConnection("tenant_{$tenantId}");}switchTenant(42);$orders=DB::table('orders')->get();print_r($orders->toArray());逐行解释:functionswitchTenant(int$tenantId):void每次请求进来,根据租户ID切换数据库连接,后续所有查询都走这个租户的库。DB::addConnection(['driver'=>'sqlite','database'=>"/data/tenant_{$tenantId}.db",],"tenant_{$tenantId}");动态注册一个新连接,连接名用租户ID区分。生产环境把 sqlite 换成 mysql,database 换成对应的库名。DB::setDefaultConnection("tenant_{$tenantId}");把这个连接设为默认,之后DB::table()、Eloquent 查询全走这里,不用每次指定连接名。---三、PostgreSQLRLS行级安全 先在 PostgreSQL 建策略(只需一次):ALTERTABLEordersENABLEROWLEVELSECURITY;CREATEPOLICYtenant_policyONordersUSING(tenant_id=current_setting('app.tenant_id')::int);PHP侧:<?php$pdo=newPDO('pgsql:host=127.0.0.1;dbname=app','appuser','pass');$tenantId=5;$pdo->exec("SET app.tenant_id ={$tenantId}");$rows=$pdo->query("SELECT * FROM orders")->fetchAll(PDO::FETCH_ASSOC);print_r($rows);逐行解释:ALTERTABLEordersENABLEROWLEVELSECURITY;给表开启行级安全,开了之后没有策略覆盖的行默认全部不可见。CREATEPOLICYtenant_policyONordersUSING(tenant_id=current_setting('app.tenant_id')::int);策略规则:只有 tenant_id 等于当前会话变量 app.tenant_id 的行才可见。::int是 PostgreSQL 的类型转换,因为 current_setting 返回字符串。$pdo->exec("SET app.tenant_id ={$tenantId}");设置当前连接的会话变量,PostgreSQL 的RLS策略会读这个值。这一行之后,这条连接上的所有查询都被数据库层自动过滤,PHP代码里完全不用写WHEREtenant_id=?$rows=$pdo->query("SELECT * FROM orders")->fetchAll();直接查全表,但数据库只返回属于当前租户的行,隔离在DB层完成,PHP层感知不到。---三种方式对比一句话: ┌────────────────┬────────────┬──────────────────────────┐ │ 方式 │ 隔离在哪层 │ 适合场景 │ ├────────────────┼────────────┼──────────────────────────┤ │GlobalScope │ORM层 │ 小项目,共库 │ ├────────────────┼────────────┼──────────────────────────┤ │ 动态连接 │ 连接层 │ 租户数据量大,需物理隔离 │ ├────────────────┼────────────┼──────────────────────────┤ │ PostgreSQLRLS│ 数据库层 │ 安全要求高,防应用层漏洞 │
http://www.jsqmd.com/news/500497/

相关文章:

  • 毕设程序java中药材科普网站 基于SpringBoot的中医药知识数字化传承平台 传统本草文化智能传播与互动系统
  • AI建站工具深度对比:哪个才是适合你的“零代码”解决方案?
  • MySQL【表的内外连接】
  • 2026年智能水肥一体机选购指南:五大实力厂商深度解析与采购建议 - 2026年企业推荐榜
  • 联想Tech World 26 重磅邀约!深圳市前海微众银行股份有限公司技代表AI 产业规模化标杆分享商业化洞察 - 博客万
  • [特殊字符] 大厂集体“卷“疯了!OpenClaw引爆AI数字员工革命,你的工作会被取代吗?
  • AI建站工具选型指南:从功能到价格,一张表看懂不同工具的差异
  • 阿里云代理商:百炼5 步实现个性化语音合成,企业级应用落地指南
  • 2026年湖南风管加工厂深度测评:五大实力厂商横向对比与选购指南 - 2026年企业推荐榜
  • vector的push_back和emplace_back核心区别
  • 金诺爱美汇科技美容有限公司知名度高吗,在本地提供哪些受欢迎的美容服务? - myqiye
  • 激光摆动焊接的Abaqus温度场分析:探索多种热源与摆动模式
  • 想一次搞定多本软著?亲测有效的申请攻略来啦!
  • 2026年百联卡如何回收,带你解锁三种有效方法 - 京回收小程序
  • 理解LangChain的结构化输出
  • 探寻山西优质观察井厂,口碑好的制造商排名 - 工业设备
  • Avalonia的生命周期 之二
  • 微搭低代码MBA培训管理系统16——商机管理
  • 英伟达 GTC 2026:黄仁勋为何认为每家公司都需要智能体人工智能战略
  • 上海凯茸包装加码安全新赛道:B1级阻燃瓦楞纸投产,构建全场景防护矩阵 - 博客万
  • OpenClaw 腾讯云服务本地访问配置指南
  • 国内首个,面向中小企业数据资产估值体系:“荟宸信科面向中小企业数据资产估值体系”正式发布(二)
  • 2026年电商仓库用大盘纸十大厂家排名,浩月职业纸业上榜 - 工业品网
  • 2026年铜陵市企业搬迁与家庭搬家服务市场主流服务商综合评估指南 - 2026年企业推荐榜
  • 个性化定制+移动应用,ERP系统新玩法的魅力你知道吗?
  • Avalonia的生命周期 之四
  • C语言教程——运算符
  • 2026年执业药师刷题app深度测评:6款热门工具对比,选对少走3个月弯路 - 孤篇横绝
  • 工程师AI工具使用笔记:高效研发辅助技巧
  • SkyReels-Text:Fine-grained Font-Controllable Text Editing for Poster Design