站点下子模块子域名访问后如何处理多个根域名支持?
1. 运行环境
1). 当前使用的 Laravel 版本?
Laravel Framework 8
2. 问题描述?
同一个站点 分为多模块 商品、商家模块
每个模块采用 二级域名访问
商品 item.aaaa.com
商家 shop.aaaa.com
目前 在 路由参数中 domain 设为
Route::group([
'domain' => domain('item'),
], function ($router) {
//商品模块路由
});
Route::group([
'domain' => domain('shop'),
], function ($router) {
//商家模块路由
});
function domain($subDomain = null){
// 根据环境 获取域名 aaaa.com | aaaa.test
$rootDomain = 'aaaa.com';
return "{$subDomain}.{$rootDomain}";
}
3. 您期望得到的结果?
需求: 同一个站点 多个 根域名可解析访问、路由可进行缓存
如 域名 aaaa.com bbbb.com cccc.com
item.aaaa.com item.bbbb.com item.cccc.com 都是可以进行访问商品模块?
问题处理如下
Route::domain('item.{sld}.{tld}')->group(function () {
Route::get('/', [IndexController::class, 'index']);
Route::get('/{id}', [IndexController::class, 'show']);
});
Route::domain('shop.{sld}.{tld}')->group(function () {
Route::get('/', [IndexController::class, 'index']);
});
public function index(string $sld, string $tld): JsonResponse
{
return response()->json([
'tld' => $tld,
'sld' => $sld,
'status' => 200,
'message' => 'Successful'
]);
}
public function show($id,Request $request): JsonResponse
{
return response()->json([
'id' => $id,
'status' => 200,
'message' => 'Successful'
]);
}
上面代码存在2个问题
1、生成url 都需要带上 sld tld 参数
route('item.index',['sld'=>'aaaa','tld'=>'com'])
route('item.show',['id'=>1,'sld'=>'aaaa','tld'=>'com'])
利用 URL::defaults 设置默认值 即可
$domain = request()->getHost()?? config('app.domain');// 请求中获取的根域名 或者 默认配置的域名
[ $sld, $tld ] = explode('.', $domain);
URL::defaults([ 'sld' => $sld, 'tld' => $tld ]);
// 所有生成url 的地方 就不用变化
route('item.index')
route('item.show',['id'=>1])
2、控制器中没有类型的参数写在 第1、2为 会变成 sld tld 的值
public function show($id,Request $request);
curl http://item.laravel.it/99
{
"id": "laravel", // 这里预期是 id参数
"status": 200,
"message": "Successful"
}
路由参数会按路由定义的顺序依次注入到路由回调或者控制器中 - ,而不受回调或者控制器的参数名称的影响。
问题处理
原理 只要在调度控制器方法前 去除 路由中的参数即可
Illuminate\Routing\Route 中 有一个 forgetParameter 方法
重写
class SubstituteBindings extends \Illuminate\Routing\Middleware\SubstituteBindings
{
public function handle($request, Closure $next)
{
try {
$route = $request->route();
$route->forgetParameter('tld');
$route->forgetParameter('sld');
} catch (\Throwable $throwable) {
}
return parent::handle($request, $next);
}
}
// HTTP kernel 中
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
//xxxxxx
\App\Http\Middleware\SubstituteBindings::class, // 更改为重写的中间件
//\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
以上解决问题
- 路由可以缓存
- 生成url 不应重复传参
- 控制器方法 不用订单 域名参数