Laravel 5.0.* 中间件在处理路由之前从 url 中删除前缀语言环境

Posted

技术标签:

【中文标题】Laravel 5.0.* 中间件在处理路由之前从 url 中删除前缀语言环境【英文标题】:Laravel 5.0.* middleware to remove prefix locale from url before routes are processed 【发布时间】:2016-04-24 06:38:26 【问题描述】:

我正在寻找一种方法,使所有应用程序路由具有多个区域设置,而无需使用路由组。这是因为我使用了外部扩展包,这意味着路由在很多地方都注册了。

基本上我希望 /foo/bar 以及 /en/foo/bar、/de/foor/bar、/es/foo/bar 等都被 /foot/bar 路由识别和处理

 Route::get('foo/bar', function () 
     return App::getLocale() . ' result';
 );

所以上面会给我'en result'或'de result'或'es result'。

我已经有基于路径段设置语言环境的中间件。我试过以下没有运气。

   ...
   $newPath =  str_replace($locale,'',$request->path());

   $request->server->set('REQUEST_URI',$new_path);

 

 return $next($request);

希望这是可能的,或者有其他方法可以实现。

编辑------

根据下面的评论,我通过将以下代码添加到 public/index.php 中快速破解了它。希望这可以更好地了解我通过编辑请求对象想要实现的目标。

$application_url_segments = explode( '/', trim( $_SERVER["REQUEST_URI"], '/' ) );

$application_locale = $application_url_segments[0];

$application_locales = ['en' => 'English', 'de' => 'German'];

if ( array_key_exists( $application_locale, $application_locales ) ) 

    $_SERVER["REQUEST_URI"] = str_replace( '/' . $application_locale,'',$_SERVER["REQUEST_URI"] );


【问题讨论】:

我个人找不到任何可以轻松完成您所追求的事情的方法。虽然我可能错过了一些东西,但我查看了 laravel 和 symfonys 的 Request 类。不幸的是,我没有找到任何有价值的东西。话虽如此,您可以在public文件夹中的index.php文件中拦截请求,然后在创建请求对象之前设置$_SERVER["REQUEST_URI"],它将起作用。 我很快在 index.php 文件中尝试了一些东西,这意味着我可以在服务器变量到达 Laravel 之前对其进行编辑。但是我认为我需要更好的东西,因为我将配置用于语言环境等。 我面临同样的问题,我也无法让它工作。 Request 对象似乎是不可变的。我也在 index.php 中设置了一个快速破解,但我也将 URI 用于语言环境等,所以仍在研究中。 【参考方案1】:

这是在调用路由之前编辑 URL 的正确代码。

<?php namespace App\Providers;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Request;

class LanguageServiceProvider extends ServiceProvider 
    public function register() 
      Request::instance()->server->set('REQUEST_URI',"/uri/");
    

请注意,从 Request 实例中获取路径而不首先复制它会由于某种原因导致 REQUEST_URI 不可编辑。我假设当您调用 path() 方法时,代码库 laravel 中的某处正在初始化请求。

【讨论】:

有没有办法在 Lumen 中做到这一点? Tom C,我已经在 Laravel 5.8.36 中尝试过这个,虽然服务器变量中的 REQUEST_URI 发生了变化,但路由器并没有接收到变化的路由。有什么想法吗??【参考方案2】:

您可以通过早一点连接到应用程序来轻松实现这一点。创建一个 ServiceProvider 并创建一个 register 方法并将您的逻辑放入其中。

<?php namespace App\Providers;

use Illuminate\Support\ServiceProviders;
use Illuminate\Support\Facades\Request;

class LocaleServiceProvider extends ServiceProvider 

    // Fires during the registration of this ServiceProvider :)
    public function register(Request $request) 

        // Altar the Request object here
        // ...
        // ...

    

【讨论】:

这不起作用。由于以下错误,我收到错误 LocaleServiceProvider::register(Illuminate\Http\Request $request) must be compatible with Illuminate\Support\ServiceProvider::register() 我已使用构造函数传入应用程序实例并使用 $应用程序-> 请求。但是 - 我仍然无法让它真正改变任何东西。路线仍然处理相同 如果有帮助,我已经对上面的原始问题/详细信息进行了编辑【参考方案3】:

在 5.5 中,这些都对我不起作用。该方法很好,但对我来说,请求参数没有注入register 方法,同样instance() 不是静态方法,不应该这样调用。

但是,使用服务容器获取Request 的实例使得在ServiceProviders register 方法中解析请求路径之前更改请求路径成为可能:

public function register()

  $this->app->make('Illuminate\Http\Request')->instance()->server->set('REQUEST_URI',"/what/ever/");

我希望这对某人有帮助!

干杯

edit:Pastor 的回答在技术上更正确,因为他使用 Facade 而不是实际的 Class。但是,register 的注入都不起作用,但您也可以使用:

use \Illuminate\Support\Facades\Request
//...
public function register()

  Request::instance()->server->set('REQUEST_URI',"/what/ever/");

【讨论】:

以上是关于Laravel 5.0.* 中间件在处理路由之前从 url 中删除前缀语言环境的主要内容,如果未能解决你的问题,请参考以下文章

将自定义中间件添加到 Laravel Passport 端点

Laravel - 将变量从中间件传递到控制器/路由

Laravel Pipeline 组件的实现

Laravel 5.2 - 在中间件请求中获取路由组名称

在 Laravel 5.3 的中间件中访问路由 URL 参数

Laravel 5.8:从 javascript 但不是从浏览器调用路由时忽略中间件