How to append a trailing slash in every routes in Laravel?

Asked by Anonymous on 03 May 2019 6552 Views

Jiwan on 03 May 2019


Adding a trailing slash to a url is unnecessary most of the times but comes to use in cases where you are working on a website that has been online for a couple of years and all the urls in the past used to be with a trailing slashes.

Since, the urls with trailing slashes are already indexed by search engines, your client might not want to mess things up by submitting a new set of urls to search engines without trailing slashes. You might know search engines treat url with and without trailing slashes as different entities and laravel does not allow you to add trailing slash at the end of the url unless you are pointing to a directory.

Let's see how to append a trailing slash in every routes in laravel.

Problem With Laravel

Laravel includes a block of code in its .htaccess file that redirects any url with trailing slash to non slashed url by default if the uri is not pointing to a directory. You can remove that piece of code and it should work fine in case you've appended a slash to each laravel route manually.

Here's the piece of code that you should remove from the htaccess file.

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]

However, if you want to redirect all non slashed urls to the slashed ones you need to add this piece of code in your htaccess file which should work fine for the frontend routes.

# Force Trailing Slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)([^/])$ http://%{HTTP_HOST}/$1$2/ [L,R=301]

A Different Scenario

In my case, a different scenario came in to the fore as I was unable to log in to the dashboard once I added the above mentioned code. Frontend routes were working perfectly and there was no issue at all until I decided to logout of the dashboard and then log in back.

I tried a lot harder and went through a lot of blogs and forums but none of the solutions worked for me.

A Different Solution Using Middleware

Finally, I decided to try something else and that was to create a middleware that checks the uri request for the presence of trailing slash at the end. If the trailing slash is not present in the uri, then, it appends a trailing slash as I needed.

Here's the piece of code I added in the new middleware I added.
<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Str;
use Config;

class trailingSlashes
{
  /**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request  $request
  * @param  \Closure  $next
  * @return mixed
  */
  public function handle($request, Closure $next)
  {
    if (!preg_match('/.+\/$/', $request->getRequestUri()))
    {            
      $base_url = Config::get('app.url');                    
      return Redirect::to($base_url.$request->getRequestUri().'/');
    }         
    return $next($request);
  }
}

Make sure that you have defined the base url of your application in your .env file for this middleware to produce output as expected.

How to create a middleware ?

Creating a middleware is quite easy in laravel. Run the laravel composer and paste the syntax shown below. You can opt for a different name of the middleware though.

php artisan make:middleware trailingSlashes

The middleware will be created inside App/Http/Middleware directory with the same name as you provided with an wmpty closure funtion handle, update it and you are good to go.

Update Your Kernel File

Finally, you need to update your Kernel.php file inside the same App/Http/Middleware directory where you need to add the middleware name as shown below.

protected $routeMiddleware = [
  'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
  'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
  'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
  'can' => \Illuminate\Auth\Middleware\Authorize::class,
  'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
  'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
  'slashes' => \App\Http\Middleware\trailingSlashes::class,        
];

Define The Route

Now, you can use the middleware to each route that you want to control which is generally the frontend routes of group them into one and bind with the same middleware.

Route::get('blog','frontController@blogs')->middleware('slashes');

Well, this might not be the only solution but it certainly worked for me although I spent a couple of days searching for a piece of code that is already tested which I never found. Please let me know, if you have solved it some other ways or if I had done something wrong in my .htaccess file which would have made the task much simpler and faster.

Don't forget to share it with your developers and help them as well.


You must be logged in to answer a question. or