【问题标题】:How to Handle domain and sub-domain in Route using Laravel MiddleWare如何使用 Laravel MiddleWare 处理 Route 中的域和子域
【发布时间】:2021-05-03 13:47:12
【问题描述】:

在我的 Laravel-5.8 应用程序中,我有一个使用单个数据库的多公司应用程序。每个表都有一个从公司表派生的 company_id,如下所示:

id | company_name       |    subdomain
1  | Main               |
2  | Company1           |    company1
3  | Company2           |    company2

Main=>  localhost:8888/myapp
Company1=>localhost:8888/company1.myapp
Company2=>localhost:8888/company2.myapp

我创建了一个中间件:

class VerifyDomain
{
 public function handle($request, Closure $next)
 {
    $domain == "myapp"; // your company app name
    $path = $request->getPathInfo(); // should return /company1.myapp or /company2.myapp or /myapp 
    if (strpos($path, ".") !== false) { // if path has dot.
        list($subdomain, $main) = explode('.', $path);
        if(strcmp($domain, $main) !== 0){
            abort(404); // if domain is not myapp then throw 404 page error
        }
    } else{
        if(strcmp($domain, $path) !== 0){
            abort(404); // if domain is not myapp then throw 404 page error
        }
        $subdomain = ""; // considering for main domain value is empty string.
    }

    $company = Company::where('subdomain', $subdomain)->firstOrFail(); // if not found then will throw 404

    $request->session()->put('subdomain', $company); //store it in session

    return $next($request);
 }
}

我已经在 route/web.php 中有两 (2) 个路由组,wgich 看起来像这样:

Route::get('/', ['as' => '/', 'uses' => 'IndexController@getLogin']);

Auth::routes();
Route::get('/dashboard', 'HomeController@index')->name('dashboard');

  // Config Module
  Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
    Route::resource('countries', 'ConfigCountriesController');
    Route::resource('nationalities', 'ConfigNationalitiesController');
});

 // HR Module
  Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () { 
    Route::resource('designations', 'HrDesignationsController');
    Route::resource('departments', 'HrDepartmentsController');  
    Route::resource('employee_categories', 'HrEmployeeCategoriesController');

});

我有 2 个问题:

  1. 如果 subdomain 字段为 null,则路由应针对主域:Main=> localhost:8888/myapp else localhost:8888/company1.myapp 或 localhost:8888/company2.myapp

2.我如何将上面的路线组容纳到这个:

 Route::domain('localhost:8888/myapp')->group(function () {
   Route::get('/', function ($id) {
       //
    });
 });

Route::domain('localhost:8888/{subdomain}.myapp')->group(function () {
   Route::get('/', function ($company_name, $id) {
       $company = Company::where('subdomain', $subdomain)->firstOrFail();
       // send the value of $company to data to send different view data 
   });
});

【问题讨论】:

    标签: laravel


    【解决方案1】:

    我不确定我是否清楚地了解你。但是,我希望你能理解我:)

    首先你是“域”。我想这不是真正的域,而只是 uri。也许你应该像这样使用它:

    Auth::routes();
    
    $defaultDomain = config('myconfig.default_domain_name', 'myapp');
    
    // I'm not reccomend to you use localhost:8888 here.
    Route::domain('localhost:8888')
        ->group([
            'middleware' => ['veryfy_domain'] // Add your VerifyDomain Middleware here
        ], function () {
            // Here you already have a 'subdomain' param in session
    
            // If you need special logic for default domain, you can out it here
            Route::group(['prefix' => '/' . $defaultDomain], function () {
                Route::get('/', function ($id) {
                   //
                });     
            });
    
    
            // Code below will work only with companies.
            Route::group(['prefix' => '/{test}.' . $defaultDomain], function () {
                Route::get('/', ['as' => '/', 'uses' => 'IndexController@getLogin']);
                Route::get('/dashboard', 'HomeController@index')->name('dashboard');
    
                  // Config Module
                Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
                    Route::resource('countries', 'ConfigCountriesController');
                    Route::resource('nationalities', 'ConfigNationalitiesController');
                });
    
                 // HR Module
                Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () { 
                    Route::resource('designations', 'HrDesignationsController');
                    Route::resource('departments', 'HrDepartmentsController');  
                    Route::resource('employee_categories', 'HrEmployeeCategoriesController');
                });
            });
        });
    

    关于你的中间件。我是这样看的:

    class VerifyDomain
    {
        public function handle($request, Closure $next)
        {
            $request->get('domain_name', $this->getBaseDomain());
    
            $company = Company::where('subdomain', $subdomain)->firstOrFail();
    
            $request->session()->put('subdomain', $company);
    
            return $next($request);
        }
    
        // Better to store it in config
        protected function getBaseDomain()
        {
            return config('myconfig.default_domain_name', 'myapp');
        }
    }
    

    如果你真的想使用不同的域,我认为你的 nginx 中需要这样的东西:

    server_name *.myapp myapp;
    

    当然还有在您的主机文件中。

    你可以这样检查: http://company.myapp http://company1.myapp http://myapp

    配置示例:

    1. 创建新文件 your_project_dir/app/config/myconfig.php(随意命名)
    2. 将此代码放入文件中:
    return [
      'default_domain_name' => 'myapp'
    ];
    
    1. 现在您可以按照我的建议在您的代码中使用:
    config('myconfig.default_domain_name');
    

    【讨论】:

    • 非常感谢,我真的很理解你。我有两个顾虑: 1. 域是否也有子域中的所有路由? 2.你说我应该把它存储在config中。我怎么做?谢谢
    • 非常感谢@ArtemTumanov,我真的很理解你。我有两个顾虑: 1. 域是否也有子域中的所有路由? 2.你说我应该把它存储在config中。我怎么做?谢谢
    • 1.是的,这没问题。它们在一个父路由组中,您可以添加相互路由,或者如果需要,您可以将当前的一些路由放置到基域组,它仅适用于基域(/myapp,而不是 company.myapp)。 2. 很简单,只需将您的自定义配置文件添加到/app/config/。一个例子:app/config/myconfig.php。并从中返回数组:return ['default_domain_name' => 'myapp']; 它将与答案中的代码一起使用。 Doc
    • 请给我一份 myconfig.php 的内容(应该是什么)的样本。其次,如果我是实时服务器,我用什么来替换 localhost:8888 ,如 Route::domain('localhost:8888')
    • 你应该把这个放在配置中:return ['default_domain_name' => 'myapp'];。我认为你不需要domain('localhost:8888')。只需使用 Route::group()
    猜你喜欢
    • 2022-07-22
    • 2021-05-03
    • 2021-07-08
    • 2010-11-06
    • 2018-01-27
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 2020-12-06
    相关资源
    最近更新 更多