站点下子模块子域名访问后如何处理多个根域名支持?

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 不应重复传参
  • 控制器方法 不用订单 域名参数
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3
Route::domain('item.{sld}.{tld}')->group(function () {
    Route::get('/', [IndexController::class, 'index']);
});
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'
    ]);
}
curl http://item.laravel.it
{
    "tld": "it",
    "sld": "laravel",
    "status": 200,
    "message": "Successful"
}
2年前 评论
liushoukun (楼主) 2年前
liushoukun (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!