laravel 使用前缀或域进行路由
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28482985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Route using either a prefix or a domain
提问by John Hickling
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.
我正在开发一个平台,该平台允许用户在主网站域的子文件夹中运行自己的站点,或者为他们的站点映射自定义域。
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.
当使用自定义域时,每个路由的 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 中实现这一点,以处理一个路由中的两种请求类型,并成功地使用反向路由根据传递给它的参数生成适当的 URL。
Below is an example of using the prefix
以下是使用前缀的示例
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] )
and be returned
并被退回
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] )
and be returned
并被退回
http://www.johnboy.com/photos/123.html
回答by lukasgeiter
This is a pretty tricky question so expect a few not so perfect workarounds in my answer...
这是一个非常棘手的问题,所以在我的回答中期待一些不太完美的解决方法......
I recommend you read everything first and try it out afterwards. This answer includes several simplification steps but I wrote down whole process to help with understanding
我建议您先阅读所有内容,然后再尝试。这个答案包括几个简化步骤,但我写下了整个过程以帮助理解
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])
(No worries we will get rid of domain.
in the URL generation later...)
(不用担心我们稍后会domain.
在 URL 生成中删除...)
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.
下一个问题是 Laravel 不允许像'domain' => '{users_domain}'
. 它适用于生成 URL,但如果您尝试实际访问它,您会得到 404。您问这个问题的解决方案是什么?您必须创建一个额外的组来侦听您当前所在的域。但前提是它不是您网站的根域。
For simplicity reasons let's first add the application domain to your config. I suggest this in config/app.php
:
为简单起见,让我们首先将应用程序域添加到您的配置中。我建议这样做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... 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:
Soooo...我们得到了我们的路线。然而,即使只有一条路线,这也相当混乱。为了减少代码重复,您可以将实际路由移动到一个(或多个)外部文件。像这样:
app/Http/routes/photos.php
:
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']);
And then the new routes.php
:
然后是新的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';
});
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
beforevendor/autoload.php
is loaded:
现在唯一缺少的是自定义 URL 生成功能。不幸的是,Laravelroute()
无法处理这个逻辑,所以你必须覆盖它。例如app/helpers.php
,使用自定义帮助函数创建一个文件,并在加载bootstrap/autoload.php
之前要求它vendor/autoload.php
:
require __DIR__.'/../app/helpers.php';
require __DIR__.'/../vendor/autoload.php';
Then add this function to the helpers.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);
}
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.
您可以完全按照您的要求调用此函数,并且它route()
在选项和传递参数方面的行为与正常情况一样。