Laravel 本地化与 Route Resource 参数混淆

Posted

技术标签:

【中文标题】Laravel 本地化与 Route Resource 参数混淆【英文标题】:Laravel Localisation messing with Route Resource parameter 【发布时间】:2021-01-07 22:33:59 【问题描述】:

在我的第二次尝试中,我通过使用Route::groupprefixes 在使用routeMiddleware Kernel 的URL 的第一段中的locale 为我正在开发的网站实现了多语言实现。它工作得很好,除非用parameters 检索路由Resources

该实现有一个小问题,因为某种原因它将parameter 变成%2Fid(这是不正确的)并且不检索我的PublicGalleriesController 请求的资源。我不明白为什么,因为当我将鼠标悬停在生成的锚点 href 上时,我看到了正确的 url 格式。但是当我点击它时,会给出一个带有混乱 url 的 404 Not Found 消息。

web.php这是我的路由组,用一个函数封装了所有路由

Route::group([
    'prefix' => 'locale',
    'middleware' => 'setlocale',
], function() 

   // all my routes are within this route group including:
   Route::resource('gallery', 'PublicGalleriesController');

   Auth::routes();

   Route::group(['middleware' => 'auth'], function() 

       ...

   );

);

App/Http/Middleware/Localisation.php 路由通过Kernel.php路由的中间件

public function handle($request, Closure $next)
    
        \App::setLocale($request->segment(1));
        return $next($request);
    

PublicGalleriesController.php 从模型中检索图像路径并将其返回到客户端视图

    public function show($id)
    
        // Show gallery group images for given group id
        $pics = null;
        $path = null;
        $path = GalleryGroup::find($id);
        
        $pics = Gallery::select('imagefilename', 'group_id')->where('group_id', $id)->orderBy('id', 'asc')->get()->toArray();

        return view('gallery.show', compact('pics', 'path'));
    

当我将鼠标悬停在index.blade 上可见的画廊组照片链接上时,它在浏览器左角显示为:localhost/en/gallery/41index.blade 检索图库组主键并在循环中构建 html 锚链接:<a href=" url(app()->getLocale(), 'gallery/' . $item['id']) ">$item['descrp']</a>

当我单击此链接时,它应该通过PublicGalleriesController 运行show 函数并检索所有这些画廊组照片,但返回一个404 Not Found,浏览器中的URL 显示localhost/en/gallery%2F41%2F 我相信是一个 Url 编码的正斜杠。

php artisan route:list 显示show 资源如下:

| Domain | Method    | URI                         | Name         | Action   
         | Middleware                              |
+--------+-----------------------------------------+--------------+-----------------------
|        | GET|HEAD  | locale/gallery/gallery  | gallery.show | App\Http\Controllers\PublicGalleriesController@show   
         | web,setlocale                           |

有人可以帮我理解为什么网址变得如此混乱吗?

Laravel 版本:5.6.39

【问题讨论】:

附注,您应该在发布问题时始终包含您使用的 Laravel 版本 【参考方案1】:

url 助手的签名是:

function url($path = null, $parameters = [], $secure = null)

$parameters 是一个参数数组,而不是路径,因此它对您正在使用的 / 进行编码,因为参数是 URL 的一部分而不是路径。

您可以调整对url 的调用以获得更完整的路径或使用parameters 数组作为附加段,而不是路径:

url(app()->getLocale() .'/gallery/'. $item['id']); // 1 argument
url(app()->getLocale() .'/gallery', [$item['id']]); // 2 arguments
url(app()->getLocale(), ['gallery', $item['id']]);  // 2 arguments

您也可以使用route 助手:

route('gallery.show', ['locale' => app()->getLocale(), 'gallery' => $item['id']]);

如果您不想为要使用 route 帮助器生成的所有 URL 传递 locale,则可以调整中间件以为此参数设置默认值:

public function handle($request, Closure $next)

    App::setLocale($locale = $request->route('locale'));

    URL::defaults(['locale' => $locale]); // set default

    return $next($request);

现在您不必传递该参数:

route('gallery.show', ['gallery' => ...]);

如果您不想将locale 参数传递给您的所有路由“动作”(控制器方法和闭包),也可以这样做。您可以在返回响应之前向该中间件添加这样的行:

$request->route()->forgetParameter('locale');

【讨论】:

很多方法可以尝试。谢谢。我按照你说的添加了参数,url看起来正确,但我仍然收到以下错误:Missing required parameters for [Route: gallery.show] [URI: locale/gallery/gallery]. 这就是为什么我给你一个调整中间件以删除 locale 参数的例子,所以它不会将它传递给你的控制器操作(答案的最后一行)......因为你有默认情况下 2 个路由参数它会将 2 个参数传递给您的控制器,第一个是 locale,因此您将 locale 值作为第一个参数...。您可能应该养成将参数命名为的习惯你的方法也匹配路由参数 您应该在调用route(..., ['locale' => ...]) 时为参数使用关联数组,但如果您尝试生成到gallery.show 路由的路由,您将缺少“gallery”参数,因为您没有'不知道您正在为哪个路由生成该 URL(当前是动态的)您不能硬编码您不知道的参数...您将不得不以不同的方式进行操作,可能是通过从当前路线,合并区域设置更改并将其用作route 方法的参数...但这超出了您的问题范围 Route::getCurrentRoute()->getParameters() 给你一个小提示;-) ...也许你想让自己的助手为你调用route 并与这些参数合并......如果你有麻烦我可以为你添加一些东西到这个答案......路由器和 URLGenerator 都是“可宏的”,你可以在运行时向它们添加你自己的方法,如果你不想做一个全局的另一个可能的选择辅助函数 对不起...方法是parameters不是getParameters

以上是关于Laravel 本地化与 Route Resource 参数混淆的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 本地化无法按需要工作

Laravel - Route::resource 与 Route::controller

Laravel 4 - Route::resource 与 Route::controller。使用哪个?

Laravel Route 模型与关系绑定

Laravel route() 返回裸 IP 地址而不是域

Laravel - 使用 Redirect::route() 添加斜杠