Laravel 9+Spatie多租户:如何一次性获取所有租户表数据?
Laravel 9 + Spatie Multitenancy v2 跨租户获取所有用户实现方案
方案一:遍历租户批量查询(通用场景)
通过遍历所有租户,切换到对应租户的数据库连接查询用户,最后合并结果集合。
use App\Models\Tenant; use App\Models\User; $allUsers = collect(); // 遍历所有租户,执行查询 Tenant::all()->each(function ($tenant) use (&$allUsers) { $tenant->makeCurrent(); // 切换到当前租户连接 $tenantUsers = User::select('id', 'name', 'email')->get(); // 按需选择字段,提升性能 $allUsers = $allUsers->merge($tenantUsers); }); Tenant::forgetCurrent(); // 切回系统连接,避免后续操作受影响 // 后续可对$allUsers进行分页、排序等处理 return $allUsers;
注意事项:
- 租户数量较多时会触发多次数据库查询,存在N+1性能问题,可结合缓存优化。
- 若需实时数据,可限制单次查询的租户数量,或使用游标分批处理。
方案二:利用数据库视图(租户数据库同实例场景)
如果所有租户的数据库都在同一数据库实例下(如MySQL的不同库),可创建跨库视图聚合所有租户的用户数据,直接通过系统连接查询。
- 创建跨库视图(以MySQL为例):
CREATE VIEW all_tenant_users AS SELECT id, name, email, 'tenant_1' AS tenant_identifier FROM tenant_1.users UNION ALL SELECT id, name, email, 'tenant_2' AS tenant_identifier FROM tenant_2.users;
新增租户时需手动或通过代码自动向视图添加UNION ALL语句
- 创建对应视图的模型:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class AllTenantUser extends Model { protected $table = 'all_tenant_users'; protected $connection = 'system'; // 指定使用系统连接 }
- 查询数据:
$allUsers = AllTenantUser::all();
注意事项:
- 仅适用于租户数据库在同一实例的场景,视图需随租户新增同步更新。
- 查询性能优于遍历方案,但数据实时性依赖视图更新频率。
方案三:使用Spatie内置方法简化遍历
Spatie Multitenancy v2提供了executeForAllTenants静态方法,可批量对所有租户执行闭包逻辑,本质与方案一一致,但更符合包的使用规范。
use App\Models\User; use App\Models\Tenant; $allUsers = collect(); Tenant::executeForAllTenants(function () use (&$allUsers) { $allUsers = $allUsers->merge(User::select('id', 'name', 'email')->get()); }); Tenant::forgetCurrent(); return $allUsers;
优化建议
- 分页处理:用户数量较多时,避免一次性拉取全部数据,可先统计总用户数后分页查询。
- 缓存策略:对非实时数据,可将查询结果缓存(如Redis),设置合理过期时间,降低数据库压力。
- 字段筛选:仅查询业务所需字段,避免拉取冗余数据。
内容的提问来源于stack exchange,提问作者Monish Khatri
相关产品推荐
相关产品推荐

