Laravel - CNAME + 子域路由

问题描述 投票:0回答:3

我的路线设置如下:

<?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
与自定义域名不同,我的
$router->pattern('domain', '[a-z0-9.]+');
中有
RouteServiceProvider.php
以允许
{domain}
作为完整域名。

php laravel laravel-5 laravel-routing
3个回答
3
投票

不幸的是,我的评论没有得到答复。这个答案假设问题是使用正常的默认路由而不是带有子域的路由。

示例:

用户正在访问 sub.website.com,但 route() 返回 website.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() 函数希望您提供 {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'

}

您可以通过 Request 对象访问您的参数来解决此问题。

public function getIndex(Request $request)
{

    $id = $request->id;

    $param2 = $reqeust->param2;

}

0
投票

整个域不能有通配符,至少不能有一个通配符。您可以执行以下操作:

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

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

我还建议使用这个包,它可能对你想做的事情有帮助。


0
投票

我自己已经回答了(至少部分):使用子域和域通配符在 Laravel 中创建路由

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

考虑:

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);
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.