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.

Marc Brillault
  • 1,902
  • 4
  • 21
  • 41
  • 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](https://googlewebmastercentral.blogspot.fr/2010/04/to-slash-or-not-to-slash.html)) – Marc Brillault Feb 09 '16 at 09:19
  • 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. – Marc Brillault Feb 09 '16 at 09:36

1 Answers1

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");
Jehad Ahmad Jaghoub
  • 1,225
  • 14
  • 22