我有一个本地化为多种语言的网站。每个公共路由都以区域设置密钥为前缀(例如/{locale}/foo/bar
),由中间件捕获并应用。
当生成指向其他页面的URL时,我最终需要将当前语言环境提供给每个URL,如下所示:
<a href={{ route('foo.bar', ['locale' => app()->getLocale()]) }}">Foo Bar</a>
否则输出网址将包含%7Blocale%7D
,这会打破它。这让我感到不必要的冗长。是否没有办法为给定的命名参数指定默认值,这样如果没有为'locale'
显式提供任何值,它可以默认为当前语言环境的任何值?
我已经检查过UrlGenerator类,但是我没有看到任何相关效果。
Route类有一个默认属性,但它似乎只用作将路由绑定到当前请求的一部分。
最终,这不是一个大问题,只是想知道是否有人对如何节省一点理智有任何想法。
答案 0 :(得分:0)
定义路线时,请使用默认值为的可选变量:
路线:
Route::get('{locale?}/foo/bar', 'Controller@fooBar');
控制器:
public function __construct()
{
$this->locale = session()->has('locale') ? session('locale') : 'en';
}
public function fooBar($locale = null)
{
$locale = $locale ?: $this->locale;
}
OR:
public function fooBar($locale = 'en')
{
$locale = $locale ?: $this->locale;
}
无论您何处致电路线:
<a href="{{ route('foo.bar', null) }}">Foo Bar</a>
您可以选择将构造函数放在所有其他控制器都扩展的BaseController类中。
可能有更好的方法可以做到这一点,但这样可以避免在任何调用路径的地方都包含语言环境。
答案 1 :(得分:0)
没有内置的方法可以做到这一点,但我设法通过扩展UrlGenerator来实现所需的结果
for($i = 1; $i <= 10; $i++) {
for($j = 0; $j < 20; $j++)
echo $j . ' ' . $i . '<br>';
echo '<br>';
}
然后将我们的子类重新绑定到服务容器
<?php
namespace App\Services;
use Illuminate\Routing\UrlGenerator as BaseGenerator;
use Illuminate\Support\Arr;
class UrlGenerator extends BaseGenerator
{
protected $default_parameters = [];
public function setDefaultParameter($key, $value){
$this->default_parameters[$key] = $value;
}
public function removeDefaultParameter($key){
unset($this->default_parameters[$key]);
}
public function getDefaultParameter($key){
return isset($this->default_parameters[$key]) ? $this->default_parameters[$key] : null;
}
protected function replaceRouteParameters($path, array &$parameters)
{
if (count($parameters) || count($this->default_parameters)) {
$path = preg_replace_sub(
'/\{.*?\}/', $parameters, $this->replaceNamedParameters($path, $parameters)
);
}
return trim(preg_replace('/\{.*?\?\}/', '', $path), '/');
}
protected function replaceNamedParameters($path, &$parameters)
{
return preg_replace_callback('/\{(.*?)\??\}/', function ($m) use (&$parameters) {
return isset($parameters[$m[1]]) ? Arr::pull($parameters, $m[1]) : ($this->getDefaultParameter($m[1]) ?: $m[0]);
}, $path);
}
}
然后我需要做的就是从Locale中间件将默认语言环境注入UrlGenerator
class RouteServiceProvider extends ServiceProvider
{
public function register(){
parent::register();
//bind our own UrlGenerator
$this->app['url'] = $this->app->share(function ($app) {
$routes = $app['router']->getRoutes();
$url = new UrlGenerator(
$routes, $app->rebinding(
'request', function ($app, $request) {
$app['url']->setRequest($request);
}
)
);
$url->setSessionResolver(function () {
return $this->app['session'];
});
$app->rebinding('routes', function ($app, $routes) {
$app['url']->setRoutes($routes);
});
return $url;
});
}
//...
}
现在public function handle($request, Closure $next, $locale = null) {
//...
$this->app['url']->setDefaultParameter('locale', $locale);
return $next($request);
}
会自动将当前区域设置绑定到路由,除非明确提供另一个区域设置。
答案 2 :(得分:0)
您也可以在中间件上使用URL默认值:
$date = date('2018-01-01');
$date_today = new DateTime($date);
$curr_weeknr = $date_today->format("W");
$six_weeks_ago = $curr_weeknr - 6;