On my second try I implemented a Multi lingual implementation for a site I am working on by using a Route::group
that prefixes
the {locale}
in the first segment of the url using routeMiddleware Kernel
. It works very well except when retrieving route Resources
with parameters
.
The implementation has a hiccup in that for some reason it turns the parameter
into %2F{id}
(which is not correct) and do not retrieve the resource that my PublicGalleriesController
requested. I do not understand why, because when I hover over the generated anchor href
I see the correct url format. But when I click it give a 404 Not Found
message with the messed up url.
web.php This is my route group that encapsulates all routes with a function
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 Route Middleware that is routed through Kernel.php
public function handle($request, Closure $next)
{
\App::setLocale($request->segment(1));
return $next($request);
}
PublicGalleriesController.php Retrieves image paths from model and returns it to client view
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'));
}
When I hover over a gallery group photo link that is visible on the index.blade
it shows in the browser left corner as: localhost/en/gallery/41
. The index.blade
retrieves the gallery group primary keys and builds html anchor links in a loop: <a href="{{ url(app()->getLocale(), 'gallery/' . $item['id']) }}">{{$item['descrp']}}</a>
When I click this link it should via the PublicGalleriesController
run the show
function and retrieve all those gallery group photos but instead returns a 404 Not Found
with the url in the browser showing localhost/en/gallery%2F41
. The %2F
I believe is a Url encoded forward slash.
php artisan route:list
shows the show
resource as follows:
| Domain | Method | URI | Name | Action
| Middleware |
+--------+-----------------------------------------+--------------+-----------------------
| | GET|HEAD | {locale}/gallery/{gallery} | gallery.show | App\Http\Controllers\PublicGalleriesController@show
| web,setlocale |
Can someone please help me to understand why the url is becoming so messy?
Laravel version: 5.6.39
The signature for the url
helper is:
function url($path = null, $parameters = [], $secure = null)
$parameters
is an array of parameters, not a path, so it is encoding the /
that you are using, since parameters are a segment of the URL not a path.
You can adjust the call to url
to have a more full path or use the parameters
array as the additional segments, not paths:
url(app()->getLocale() .'/gallery/'. $item['id']); // 1 argument
url(app()->getLocale() .'/gallery', [$item['id']]); // 2 arguments
url(app()->getLocale(), ['gallery', $item['id']]); // 2 arguments
You can also use the route
helper:
route('gallery.show', ['locale' => app()->getLocale(), 'gallery' => $item['id']]);
If you don't want to have to pass locale
in for all the URLs you want to generate with the route
helper you can adjust your middleware to set a default for this parameter:
public function handle($request, Closure $next)
{
App::setLocale($locale = $request->route('locale'));
URL::defaults(['locale' => $locale]); // set default
return $next($request);
}
Now you don't have to pass that parameter:
route('gallery.show', ['gallery' => ...]);
If you wanted to not have the locale
parameter passed to all your route "actions" (Controller methods and closures) that can be done as well. You can add a line like so to that middleware before you return the response:
$request->route()->forgetParameter('locale');