我构建了一个简单的方法来标识租户与子域,例如:user1.example.com
,租户将是user1,另一方面,如果user1不存在,user1.example.com
将响应404
。
我在服务提供者中定义了一个Macro
,如下所示:
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->singleton('tenancy', function (Application $app) {
return new TenancyMananger($app);
});
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
Route::macro('tenancy', fn (Closure $groups) => Route::domain(sprintf('{tenant}.example.com'))
->middleware(['tenancy'])
->group($groups));
Route::model('tenant', Tenant::class);
}
然后,使用middleware
初始化并标识租户:
public function handle(Request $request, Closure $next)
{
Tenancy::init($request->tenant);
return $next($request);
}
我覆盖了Tenant model
上的getRouteKeyName
方法,以使用id
以外的数据库列:
public function getRouteKeyName()
{
return 'domain';
}
最后,我编写了下面的特性测试用例对其进行测试:
\Illuminate\Support\Facades\Route::tenancy(function () {
\Illuminate\Support\Facades\Route::get('/test', fn () => 'hello world');
});
$tenant = Tenant::factory()->create([
'domain' => 'demo',
'name' => 'demo name',
]);
$this->get('http://demo.example.com/test')->assertStatus(200);
$this->assertEquals(Tenancy::tenant()->id, $tenant->id);
$this->assertEquals(Tenancy::domain(), $tenant->domain);
$this->assertEquals(Tenancy::name(), $tenant->name);
但我会得到错误:
testing.ERROR: App\TenancyMananger::init(): Argument #1 ($tenant) must be of type App\Models\Tenant, string given
看起来route
没有触发模型绑定,因此$request->tenant
int the middleware
将字符串(子域)传递到TenancyMananger
中。
你知道这里会发生什么吗?否则我不能这样写测试...
如有任何帮助或指导,不胜感激。
我使用的是PHP 8.1、Laravel 10.x-dev和phpunit v9.5.27。
谢谢。
1条答案
按热度按时间iklwldmw1#
当你使用这个
Tenancy::init($request->tenant);
Laravel将Model绑定到路径上。并确保已将
Tenancy
类添加到$routeMiddleware