Laravel - append a trailing slash in routes
Asked Answered
B

1

3

As I mentioned several times here, I'm redoing one of my old sites with Laravel.

Another problem I encounter is the following :

  • I've got mainly two different types of urls on the old website :
    • /user-slug/ for the users homepage, and
    • /user-slug/content-slug.html for one of its content

I managed to recreate the second one, but Laravel always trims the last slash when I try to create a link to the user route, and I end with an url like /user-slug

I don't want to lose any SEO when switching the old website to Laravel, so I wanted to know whether it was possible to force Laravel to append the trailing slash on one url ?


My code so far:

app\Providers\RouteServiceProvider.php :

public function boot(Router $router)
{
    $router->pattern('user', '[a-zA-Z0-9_-]+');
    $router->pattern('content', '[a-zA-Z0-9_-]+');
    parent::boot($router);
}

app\Http\routes.php :

Route::group(['middleware' => ['web']], function () {
    Route::get('/', [
        'as'   => 'index',
        'uses' => 'BaseController@index',
    ]);

    Route::get('/{user}/', [
        'as'   => 'user',
        'uses' => 'UserController@show',
    ]);

    Route::get('/{user}/{content}.html', [
        'as'   => 'content',
        'uses' => 'ContentController@show',
    ]);
});

views/home.blade.php :

{!! Html::linkRoute('user', $content['user']['name'], [$content->user->slug]) !!}

If there is no workaround, I'll use a .htaccess file to redirect all /user-slug/ urls to /user-slug, but if I can avoid it, that would be cool.

Broderickbrodeur answered 9/2, 2016 at 7:11 Comment(2)
As the version without slash is considered as a file, and the version with slash is considered as a directory, they could reference two different contents, so they are considered as two different urls (Source webmaster central)Broderickbrodeur
Choosing between the two types of urls doesn't affect SEO, but in my case, I already have existing urls with the slash. The new urls without the slash will be considered as new urls, and even if I 301 redirect the old scheme to the new, I might experience some SEO loss for a while.Broderickbrodeur
D
0

Humm I think it looks possible through middleware eg.

  1. $ php artisan make:middleware slashesMiddleware
  2. go to app/Http/Middleware/slashesMiddleware.php and fill it with this content

    <?php
    
    namespace App\Http\Middleware;
    use Closure;
    
    class slashesMiddleware
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next, $flag)
        {
            if ($flag=="remove") {
                if (ends_with($request->getPathInfo(), '/')) {
                    $newval = rtrim($request->getPathInfo(), "/");
                    header("HTTP/1.1 301 Moved Permanently");
                    header("Location:$newval");
                    exit();
                }
            } else {
                if (!ends_with($request->getPathInfo(), '/')) {
                    $newval =$request->getPathInfo().'/';
                    header("HTTP/1.1 301 Moved Permanently");
                    header("Location:$newval");
                    exit();
                }
            }
            return $next($request);
        }
    }
    
  3. this add 2 methods first "add" trailing slash to route or "remove" it

  4. add it list of middlewares of you app go to app/Http/Kernel.php under the array $routeMiddleware

        protected $routeMiddleware = [
            'auth' => \App\Http\Middleware\Authenticate::class,
            'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
            'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
            'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
            'can' => \Illuminate\Auth\Middleware\Authorize::class,
            'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
            'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
            'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
            'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
            'slashes' => \App\Http\Middleware\slashesMiddleware::class,
        ];
    
    1. finnaly added it to any route you want or you can add it to all route from $middleware array

example of usage

Route::get('/compare', 'WebRouteController@compare')->middleware("slashes:add");
Delative answered 7/11, 2019 at 2:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.