Laravel - CNAME +子域路由

时间:2016-05-21 07:56:26

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

3 个答案:

答案 0 :(得分:2)

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

示例:

用户正在访问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;

}

答案 1 :(得分:0)

您不能在整个域中使用通配符,至少不能使用一个通配符。你能做的是以下几点:

<html>
  <title>Report Generation</title>
  <head>
  <HTA:APPLICATION 
    APPLICATIONNAME="Master Report Generation"
  SCROLL="yes"
  SINGLEINSTANCE="yes"
  WINDOWSTATE="normal">
  </head>

<style>
BODY
{
background-color: buttonface;
Font: arial,sans-serif
margin-top: 10px;
margin-left: 20px;
margin-right: 20px;
margin-bottom: 5px;
}
.button
{
width: 91px;
height: 25px;
font-family: arial,sans-serif;
font-size: 8pt;
}
td
{
font-family: arial,sans-serif;
font-size: 10pt;
}                     
#scroll
{
height:100%;
overflow:auto;
}
SELECT.FixedWidth 
{
width: 17em;  /* maybe use px for pixels or pt for points here */
}
</style>


<script language="vbscript">

Option Explicit    

Dim WinWidth : WinWidth = 350
Dim WinHeight : WinHeight = 250
Window.ResizeTo WinWidth, WinHeight

  Sub CheckBoxChange

    If CheckBox(0).Checked Then
    ExecuteScoreCard()
    Else
    MsgBox "CheckBox is not checked"
    End If

  End Sub

  Sub ExecuteScoreCard() 
    Dim sitecode
    Dim objExcel  
    Dim objApp  
    Dim objWorkbook
    Dim objSheet
    Dim scriptdir
    Dim oFSO
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    <b>scriptdir = oFSO.GetParentFolderName(WScript.ScriptFullName)</b>

    Set objExcel = CreateObject("Excel.Application")
    Set objWorkbook = objExcel.Workbooks.Open(scriptdir & "\SCORECARD.xlsm")
    Set objSheet = objWorkbook.Worksheets("Cover Tab")  

    objSheet.Cells(4, 2) = sitecode

    objExcel.Run "RefreshConns"
    WScript.Sleep 75000 

    objExcel.ActiveWorkbook.SaveAs scriptdir & "\Scorecards\" & "SCORECARD_" & sitecode & "_" & Year(Now()) & Month(Now()) & Day(Now()) & "_" & Hour(Now()) & Minute(Now()) &".xlsm", 52
    objExcel.ActiveWorkbook.Close
    objExcel.Quit   

    MsgBox("Successfully generated scorecard.")
End Sub 

</script>

<body>
Site Code: <input type="inputbox" name="sitecode">
  <br>
  <input type="checkbox" name="CheckBox"> Scorecard
  <br>
  <input type="checkbox" name="CheckBox"> Report2
  <br>
  <input type="checkbox" name="CheckBox"> Report3
  <br>
  <br>
  <input type="submit" name="accept" value="Submit" onclick="CheckBoxChange">
</body>
</html>

只需确保此群组是路径文件中的最后一个群组,它将充当域名上的后备群组,并将提供与之前任何域名不匹配的请求。

另外,我建议您使用this package,这可能会对您要做的事情有所帮助。

答案 2 :(得分:0)

至少部分由我自己在这里回答:Creating a route in Laravel using subdomain and domain wildcards

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

考虑:

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);
}