Laravel 5.5 locale as prefix in url

2019-03-21 22:21发布

问题:

At the moment I have in my routes/web.php the following:

Route::group( [ 'prefix' => '{locale?}', 'middleware' =>\App\Http\Middleware\Locale::class ], function (\Illuminate\Routing\Router $router) {

    Route::get( '/', 'LandingController@index' )->name( 'home' );
    Route::get( '/hero/create', 'HeroController@create' )->name( 'hero.create' );
} );

This doesn't really work as it should be.

What I want is to have an url like this:

/create/hero    # should work with the default locale
/fr/create/hero # should use the french locale
/nl/create/hero # should use dutch locale
/               # should work with the default locale
/fr             # should use the french locale
/nl             # should use dutch locale

So I want the locale parameter optional at the beginning of the url. So far what I've managed to achieve is only to get the urls working when specifying the locale myself. I always get a not found message when I don't manually specify the locale.

I know I should be able to do it like this:

Route::get('/path/{id}/{start?}/{end?}', ['as' => 'route.name', 'uses' => 'PathController@index']);

public function index($id, $start = "2015-04-01", $end = "2015-04-30")
{
    // code here
}

But I think that's a but would mean I have to set the default locale in every controller which is a bit ugly in my opinion. Also, I think that this should be possible in a more elegant way in Laravel.

How can I set a default value for the locale prefix in my url?

回答1:

You have to think about routes generated deeply. And never use prefix as optional , so to make work all url give change in route like this

Route::get( '/', 'LandingController@index' )->name( 'home' );
Route::get( '/hero/create', 'HeroController@create' )->name( 'hero.create' );

Route::group( [ 'prefix' => '{locale}', 'middleware' =>\App\Http\Middleware\Locale::class ], function (\Illuminate\Routing\Router $router) {
    Route::get( '/', 'LandingController@index' )->name( 'home' );
    Route::get( '/hero/create', 'HeroController@create' )->name( 'hero.create' );
} );

Here is the short description in your way

/               # should work with first above route 
/create/hero    # should work with first above route
/fr/create/hero # should work with route inside prefix
/nl/create/hero # should work with route inside prefix
/fr             # should work with route inside prefix
/nl             # should work with route inside prefix

It can be solve either to put optional ({locale?}) at the last not in between, or you can just put route into a variable and put in both condition, I mean outside prefix and inside prefix.

$heroRoutes = function (\Illuminate\Routing\Router $router) {
    Route::get( '/', 'LandingController@index' )->name( 'home' );
    Route::get( '/hero/create', 'HeroController@create' )->name( 'hero.create' );
}
Route::group( [ 'middleware' =>\App\Http\Middleware\Locale::class ], $heroRoutes );
Route::group( [ 'prefix' => '{locale}', 'middleware' =>\App\Http\Middleware\Locale::class ], $heroRoutes );