Laravel - CNAME + 子域路由

Laravel - CNAME + Subdomain Routing

我的路线设置如下:

<?php

Route::group([
    'domain' => '{username}.u.'.env('APP_DOMAIN'),
], function () {
    Route::get('/', 'FrontendController@site');
});

Route::group([
    'domain' => env('APP_DOMAIN'),
], function () {
    // Regular site routes
});

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

我想要实现的是让用户拥有自己的网站,例如hello.u.domain.com,并且这些网站也可以通过 CNAME 到其子域的自定义域提供服务。使用上面的路由,通配符子域工作得很好。然而,自定义域路由永远不会被命中;每当访问子域的 CNAME 自定义域时,都会使用常规站点路由。

APP_DOMAIN和自定义域名不一样,我的RouteServiceProvider.php里面有$router->pattern('domain', '[a-z0-9.]+');允许{domain}作为完整域名。

您不能在整个域上使用通配符,至少不能使用一个通配符。您可以做的是:

Route::group([
    'domain' => '{domain}.{suffix}',
], function () {
    Route::get('/', 'FrontendController@domain');
});

只需确保该组是您的路由文件中的最后一个,它将充当域上的后备组,并将处理与之前任何域都不匹配的请求。

此外,我建议使用 this package,它可能对您尝试做的事情有所帮助。

我在这里至少部分地回答了这个问题:

简而言之,您不能将整个域作为路由文件中的参数。相反,您分配一个中间件来检查当前域,将其与您预定义的允许用户域列表进行匹配,并基于此做出一些决定(例如,在您的控制器中使用什么方法)。

考虑:

Route::group([
    'middleware' => 'domain-check',
], function () {
    Route::get('/', 'FrontendController@handle');
});

然后在您的 FrontendController 中:

public function handle(Request $request)
{
    // Information about the current user/domain is here
    $request->client;

    // An example - let's imagine that client object contains a view ID
    return response()->view($request->client->view);
}

很遗憾,我的评论没有得到答复。该答案假定问题是使用普通默认路由而不是具有子域的路由。

示例:

用户正在访问 sub.website.com 但 route() returns 网站。com/blabla 而不是 sub.website。com/blabla

您可以通过在 routes.php

中动态创建域模式来解决此问题
// routes.php
$url_parameters = @explode(".", $_SERVER['HTTP_HOST']);

if (count($url_parameters) == 3)
{
    $pattern = '{subdomain}.{domain}.{tld}';
}
else
{
    $pattern = '{domain}.{tld}';
}

Route::group(['domain' => $pattern], function () {

    Route::get('/', [
        'as' => 'get_index',
        'uses' => 'HomeController@getIndex'
    ]);

}

使用此方法会导致 route() 和控制器参数出现问题。

route()问题

在使用此方法的同时调用 route() 函数时,您将收到缺少参数的错误。 route() 函数需要您提供 {subdomain}.{domain}.{tld} 参数。

您可以通过创建自己的路由函数来解决这个问题。我将其命名为 mdroute()(多域路由)。

function mdroute($route, $parameters = [])
{

    $data = [
        'domain' => \Request::route()->domain,
        'tld' => \Request::route()->tld
    ];


    $subdomain = \Request::route()->subdomain;

    if ($subdomain) $data['subdomain'] = $subdomain;

    // You can use mdroute('blabla', 'parameter')
    // or mdroute('blabla', ['par1' => 'parameter1', 'par2' => 'parameter2'])
    //
    if (is_array($parameters))
    {
        $data = array_merge($data, $parameters);
    }
    else
    {
        $data[] = $parameters;
    }


    return route($route, $data);

}

控制器问题

参数 {sub}.{domain}.{tld} 总是发送到您的控制器。您不能像以前那样访问其他参数。

示例:

// Domain = sub.webite.com


// Your route
//
Route::get('/post/{id}/{param2}', [
    'uses' => 'PostController@getIndex'
]);

// PostController
//
public function getIndex($id, $param2)
{

    // $id will be 'sub'
    // $param2 will be 'website'

}

您可以通过请求对象访问您的参数来解决这个问题。

public function getIndex(Request $request)
{

    $id = $request->id;

    $param2 = $reqeust->param2;

}