使用前缀或域进行路由 [英] Route using either a prefix or a domain

查看:83
本文介绍了使用前缀或域进行路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个平台,允许用户在主网站域的子文件夹中运行自己的网站,或为他们的网站映射自定义域.

I am working on a platform that allows users to run their own site in either a sub folder of the main website domain, or map a custom domain for their site.

在使用自定义域时,每个路由的URL结构都稍有不同,因为它以用户名作为前缀,但是在使用自定义域时,则不使用该前缀.

When using a custom domain the URL structure for each route is slightly different in that it is prefixed with the username, but when using a custom domain then this prefix is not used.

在Route :: group中是否有一种巧妙的方法可以在一条路由中处理两种请求类型,并根据传递给它的参数成功使用反向路由来生成适当的URL.

Is there a clever way to achieve this in my Route::group to handle both request types in one route and successfully use reverse routing to produce the appropriate URL based on the parameters passed to it.

下面是使用前缀

Route::group(array( 'prefix' => 'sites/{username}'), function() {
    Route::get('/photos/{album_id}.html', array('uses' => 'Media\PhotosController@album_view', 'as' => 'photo_album'));
});

这是使用自定义域的示例

And here is an example of using a custom domain

Route::group(array('domain' => '{users_domain}'), function() {
    Route::get('/photos/{album_id}.html', array('uses' => 'Media\PhotosController@album_view', 'as' => 'photo_album'));
});

理想情况下,我希望处于可以使用任一位置的位置

Ideally I would like to be in a position where I could use either

route('photo_album', ['username' => 'johnboy', 'album_id' => 123] )

并退回

http://www.mainwebsitedomain.com/sites/johnboy/photos/123.html

或使用不同的参数调用同一条路线

or call the same route with different parameters

route('photo_album', ['users_domain' => 'www.johnboy.com', 'album_id' => 123] )

并返回

http://www.johnboy.com/photos/123.html

推荐答案

这是一个非常棘手的问题,因此请期待我的回答中一些不太理想的解决方法...

This is a pretty tricky question so expect a few not so perfect workarounds in my answer...

我建议您先阅读所有内容,然后再尝试.这个答案包括几个简化步骤,但我写下了整个过程以帮助理解

这里的第一个问题是,如果要按名称调用它们,则不能有多个具有相同名称的路由.

The first problem here is that you can't have multiple routes with the same name if you want to call them by name.

让我们通过添加路由名称前缀"来解决此问题:

Let's fix that by adding a "route name prefix":

Route::group(array( 'prefix' => 'sites/{username}'), function() {
    Route::get('/photos/{album_id}.html', array('uses' => 'Media\PhotosController@album_view',
                                                'as' => 'photo_album'));
});

Route::group(array('domain' => '{users_domain}'), function() {
    Route::get('/photos/{album_id}.html', array('uses' => 'Media\PhotosController@album_view',
                                                'as' => 'domain.photo_album'));
});

所以现在我们可以使用它来生成网址:

So now we can use this to generate urls:

route('photo_album', ['username' => 'johnboy', 'album_id' => 123] )
route('domain.photo_album', ['users_domain' => 'www.johnboy.com', 'album_id' => 123])

(不用担心,以后我们会在URL生成中摆脱domain. ...)

(No worries we will get rid of domain. in the URL generation later...)

下一个问题是Laravel不允许像'domain' => '{users_domain}'这样的完整通配符域.它可以很好地生成URL,但是如果您尝试实际访问它,则会得到404.您问的解决方案是什么?您必须创建一个额外的组,以侦听您当前所在的域.但前提是它不是您网站的根域.

The next problem is that Laravel doesn't allow a full wildcard domain like 'domain' => '{users_domain}'. It works fine for generating URLs but if you try to actually access it you get a 404. What's the solution for this you ask? You have to create an additional group that listens to the domain you're currently on. But only if it isn't the root domain of your site.

为简单起见,我们首先将应用程序域添加到您的配置中.我建议在config/app.php中:

For simplicity reasons let's first add the application domain to your config. I suggest this in config/app.php:

'domain' => env('APP_DOMAIN', 'www.mainwebsitedomain.com')

通过这种方式,还可以通过环境文件对其进行配置以进行开发.

This way it is also configurable via the environment file for development.

之后,我们可以添加此条件路由组:

After that we can add this conditional route group:

$currentDomain = Request::server('HTTP_HOST');
if($currentDomain != config('app.domain')){
    Route::group(array('domain' => $currentDomain), function() {
        Route::get('/photos/{album_id}.html', array('uses' => 'Media\PhotosController@album_view',
                                                    'as' => 'current_domain.photo_album'));
    });
}


Soooo ...我们得到了路线.但是,即使只有一条路线,这也很混乱.为了减少代码重复,您可以将实际路由移动到一个(或多个)外部文件中.像这样:


Soooo... we got our routes. However this is pretty messy, even with just one single route. To reduce the code duplication your can move the actual routes to one (or more) external files. Like this:

app/Http/routes/photos.php:

if(!empty($routeNamePrefix)){
    $routeNamePrefix = $routeNamePrefix . '.';
}
else {
    $routeNamePrefix = '';
}

Route::get('/photos/{album_id}.html', ['uses' => 'Media\PhotosController@album_view',
                                            'as' => $routeNamePrefix.'photo_album']);

然后是新的routes.php:

// routes for application domain routes
Route::group(['domain' => config('app.domain'), 'prefix' => 'sites/{username}'], function($group){
    include __DIR__.'/routes/photos.php';
});

// routes to LISTEN to custom domain requests
$currentDomain = Request::server('HTTP_HOST');
if($currentDomain != config('app.domain')){
    Route::group(['domain' => $currentDomain], function(){
        $routeNamePrefix = 'current_domain';
        include __DIR__.'/routes/photos.php';
    });
}

// routes to GENERATE custom domain URLs
Route::group(['domain' => '{users_domain}'], function(){
    $routeNamePrefix = 'domain';
    include __DIR__.'/routes/photos.php';
});


现在唯一缺少的是自定义URL生成功能.不幸的是,Laravel的route()无法处理此逻辑,因此您必须重写它.创建具有自定义帮助程序功能的文件,例如app/helpers.php,并在加载 vendor/autoload.php之前在bootstrap/autoload.php 中要求它:


Now the only thing missing is a custom URL generation function. Unfortunately Laravel's route() won't be able to handle this logic so you have to override it. Create a file with custom helper functions, for example app/helpers.php and require it in bootstrap/autoload.php before vendor/autoload.php is loaded:

require __DIR__.'/../app/helpers.php';

require __DIR__.'/../vendor/autoload.php';

然后将此功能添加到helpers.php:

function route($name, $parameters = array(), $absolute = true, $route = null){
    $currentDomain = Request::server('HTTP_HOST');
    $usersDomain = array_get($parameters, 'users_domain');
    if($usersDomain){
        if($currentDomain == $usersDomain){
            $name = 'current_domain.'.$name;
            array_forget($parameters, 'users_domain');
        }
        else {
            $name = 'domain.'.$name;
        }
    }
    return app('url')->route($name, $parameters, $absolute, $route);
}

您可以完全按照要求调用此函数,就选项和传递参数而言,它的行为与普通的route()相同.

You can call this function exactly like you asked for and it will behave like the normal route() in terms of options and passing parameters.

这篇关于使用前缀或域进行路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆