Spatie Laravel Multitenancy问题:误访问Landlord数据库users表
问题描述
在Laravel应用中集成Spatie Laravel Multitenancy时,运行应用出现以下错误:
Illuminate\Database\QueryException SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel.users' doesn't exist SELECT * FROM `users`
配置详情
数据库配置
已为租户(tenant)和主库(landlord)配置独立数据库,连接信息如下:
'tenant' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => null, 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 'landlord' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ],
多租户配置(config/multitenancy.php)
<?php use Illuminate\Broadcasting\BroadcastEvent; use Illuminate\Events\CallQueuedListener; use Illuminate\Mail\SendQueuedMailable; use Illuminate\Notifications\SendQueuedNotifications; use Spatie\Multitenancy\Actions\ForgetCurrentTenantAction; use Spatie\Multitenancy\Actions\MakeQueueTenantAwareAction; use Spatie\Multitenancy\Actions\MakeTenantCurrentAction; use Spatie\Multitenancy\Actions\MigrateTenantAction; use Spatie\Multitenancy\Models\Tenant; use Spatie\Multitenancy\Tasks\SwitchTenantDatabaseTask; return [ 'tenant_finder' => Spatie\Multitenancy\TenantFinder\DomainTenantFinder::class, 'tenant_artisan_search_fields' => [ 'id', ], 'switch_tenant_tasks' => [ SwitchTenantDatabaseTask::class, ], 'tenant_model' => Tenant::class, 'queues_are_tenant_aware_by_default' => true, 'tenant_database_connection_name' => 'tenant', 'landlord_database_connection_name' => null, 'current_tenant_container_key' => 'currentTenant', 'shared_routes_cache' => false, 'actions' => [ 'make_tenant_current_action' => MakeTenantCurrentAction::class, 'forget_current_tenant_action' => ForgetCurrentTenantAction::class, 'make_queue_tenant_aware_action' => MakeQueueTenantAwareAction::class, 'migrate_tenant' => MigrateTenantAction::class, ], 'queueable_to_job' => [ SendQueuedMailable::class => 'mailable', SendQueuedNotifications::class => 'notification', CallQueuedListener::class => 'class', BroadcastEvent::class => 'event', ], 'tenant_aware_jobs' => [ // ... ], 'not_tenant_aware_jobs' => [ // ... ], ];
环境变量(.env)
DB_CONNECTION=landlord DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=root DB_PASSWORD=
错误背景
错误触发于应用访问users表时。按照多租户架构设计,每个租户应拥有独立的users表,但当前应用似乎在访问主库(landlord)的users表,而非当前租户数据库中的对应表。
预期效果
已按文档配置租户与主库的独立数据库,期望应用能根据当前租户自动切换到对应数据库,访问users表时使用租户数据库内的表。
解决方案
1. 绑定用户模型到租户数据库连接
修改User模型,指定使用租户连接:
// app/Models/User.php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Multitenancy\Models\Concerns\UsesTenantConnection; class User extends Authenticatable { // 使用Spatie提供的trait自动关联租户连接 use UsesTenantConnection; // ... 其他模型代码 }
如果不需要全局绑定,也可以手动指定连接字段:
protected $connection = 'tenant';
2. 修复多租户配置中的主库连接
在config/multitenancy.php中,将主库连接设置为landlord:
'landlord_database_connection_name' => 'landlord',
确保主库模型(如Tenant本身)能正确使用主库连接,避免连接混淆。
3. 验证租户模型的数据库字段配置
如果自定义了租户模型,确认数据库名字段的映射正确:
// app/Models/Tenant.php(自定义租户模型时) namespace App\Models; use Spatie\Multitenancy\Models\Tenant as SpatieTenant; class Tenant extends SpatieTenant { // 若租户表中存储数据库名的字段不是默认的`database`,重写此方法 public function getDatabaseName(): string { return $this->tenant_db_name; // 替换为你的实际字段名 } }
同时确保config/multitenancy.php中的tenant_model指向正确的自定义模型。
4. 确认租户切换逻辑生效
- 检查请求域名是否已关联到对应租户记录(
DomainTenantFinder依赖域名匹配租户) - 在控制器/中间件中添加调试代码,验证当前租户和连接:
dd(tenant()?->id, tenant()?->database_name, DB::connection()->getName());
如果tenant()返回null,说明租户未被正确识别,需检查域名解析、租户记录是否存在。
5. 确保租户数据库已完成迁移
执行租户迁移命令,确保每个租户数据库都有users表:
php artisan tenant:migrate
若租户数据库未创建,可通过命令生成:
php artisan tenant:create {tenant-name} --domain={tenant-domain} --database={tenant-db-name}
6. 注册多租户中间件
检查app/Http/Kernel.php,确保添加了租户切换的核心中间件:
protected $middlewareGroups = [ 'web' => [ // ... 其他中间件 \Spatie\Multitenancy\Http\Middleware\MakeTenantCurrent::class, \Spatie\Multitenancy\Http\Middleware\EnsureValidTenantSession::class, ], 'api' => [ // ... 其他中间件 \Spatie\Multitenancy\Http\Middleware\MakeTenantCurrent::class, ], ];
7. 清理配置缓存
修改配置后清理缓存,确保新配置生效:
php artisan config:clear php artisan cache:clear
内容的提问来源于stack exchange,提问作者H.Hassan
相关产品推荐
相关产品推荐

