Laravel中,如何使用一条路由Route正则匹配多个域名?

星级:
Laravel中,如果想要一条路由Route匹配多个域名,只需将域名的部分甚至全部用一个自定义变量替换;如果想要进一步规范域名,则可以预先在路由服务提供者(RouteServiceProvider)的boot()方法中,为自定义变量定义一个正则规范,这样之后,就只有通过符合正则规范的域名才能访问相关路由。

在Laravel中,路由Route在设置域名时,理论上是不支持多域名匹配的,group()函数中的domain参数值也只接受字符串数据类型,很多开发者为了给路由匹配多个域名,可能会理所应当地为域名参数值赋上一个数组类型,或者直接赋值为一个正则表达式,比如:

[数组类型]

Route::group(['domain' => ['mob.abc.com','www.abc.com'], function () {
Route::get('/test','TestCtl@test');
});

或者

[正则表达式类型]

Route::group(['domain' => '(mob|www).abc.com'], function () {
Route::get('/test','TestCtl@test');
});

很可惜,这些方法都不能帮助开发者达到想要的效果,甚至如果采用第一种方法,传入一个数组类型的值,还会引发报错,导致全站所有路由全部失效。

如果想要实现一条路由Route匹配多个域名,其实一点也不难,只要把路由的域名值中部分用变量替代即可,比如:

Route::group(['domain' => '{sub_domain}.abc.com'], function () {

Route::get('/test','TestCtl@test');
});

以上路由,域名的子域名部分就被变量{sub_domain}替代了,而其中的{sub_domain}部分可以匹配任意值,但其余部分则必须精确匹配,也即,以上路由只能匹配处理来自*.abc.com 这个域名的请求。

如果想要实现多个主域名匹配,也可以把主域名部分或者后缀部分替换掉,甚至还可以将域名当做一个整体用变量替代,比如:

Route::group(['domain' => '{sub_domain}.{domain_name}.com'], function () {
Route::get('/test','TestCtl@test');
});

又比如

Route::group(['domain' => '{sub_domain}.abc.{domain_postfix}'], function () {
Route::get('/test','TestCtl@test');
});

再比如

Route::group(['domain' => '{domain}'], function () {
Route::get('/test','TestCtl@test');
});

另外,很多开发者可能还有限制部分路由访问的需求,比如一个网站有3个子域名,但只想让其中的2个访问该路由。这时,我们就需要在路由服务提供者(RouteServiceProvider)中预先为路由变量定义一个正则表达式,只让符合正则表达式的域名访问,而其他不符合的则一律拒绝,比如:

一个网站有3个域名:

mob.abc.com
www.abc.com
api.abc.com

其中,有一个路由只想让mob.abc.comwww.abc.com访问,这时我们就需要先在路由服务提供者(RouteServiceProvider)的boot方法中为变量{sub_domain}定义一个正则表达式

<?php


namespace App\Providers;

use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
protected $namespace = 'App\Http\Controllers';

public function boot()
{
//
$this->app['router']->pattern('sub_domain', '^(mob|www)$');

parent::boot();
}
}

然后,再按前面的方法定义路由,并在路由中使用用正则表达式规范的变量

Route::group(['domain' => '{sub_domain}.abc.com'], function () {
Route::get('/test','TestCtl@test');
});

这时,你就可以发现,该路由将只对mob.abc.comwww.abc.com生效,而通过api.abc.com访问,则将会报404错误。