70

I want to define a route with a parameter that will contain a slash / character like so example.com/view/abc/02 where abc/02 is the parameter.

How can I prevent Laravel from reading the slash as a separator for the next route parameter? Because of that I'm getting a 404 not found error now.

Laurence
  • 58,936
  • 21
  • 171
  • 212
hserusv
  • 976
  • 1
  • 7
  • 17

5 Answers5

139

Add the below catch-all route to the bottom of your routes.php and remember to run composer dump-autoload afterwards. Notice the use of "->where" that specifies the possible content of params, enabling you to use a param containing a slash.

//routes.php
Route::get('view/{slashData?}', 'ExampleController@getData')
    ->where('slashData', '(.*)');

And than in your controller you just handle the data as you'd normally do (like it didnt contain the slash).

//controller 
class ExampleController extends BaseController {

    public function getData($slashData = null)
    {
        if($slashData) 
        {
            //do stuff 
        }
    }

}

This should work for you.

Additionally, here you have detailed Laravel docs on route parameters: [ docs ]

Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
Gadoma
  • 6,475
  • 1
  • 31
  • 34
  • 4
    I disagree, this is a hack to work around a short-fall in the laravel routing. Check out my answer and laravel package which provides a fix for encoded slashes. – Artistan Sep 30 '14 at 12:37
  • 3
    It works similar in Lumen `$app->get('/documents/{document:.+}', 'DocumentController@show');` – Londeren Aug 05 '15 at 13:07
  • 2
    In my use case, I have another parameter after the "slash-parameter" like this: `url/slash%2Fparameter/12`- with a route like `url/{slashData}/{id}`. This should work, but doesn't due to laravels bug. Your "solution" would give `getData()` the whole `slash/parameter/12` and I would have to split the slash-parameter from the id myself. That's laravel's job, not mine! – Christopher K. Jan 26 '18 at 13:01
  • @Chistopher K. you can accept slash parameters perfectly just don't use url encoding on the slash; that is a separate bug in Laravel (https://github.com/laravel/framework/issues/22125). But if you use url/slash/parameter/12 for your example and then create the route like this: Route::get('/url/{slashData}/{id}', 'SomeController@someMethod')->where(['slashData' => '[^/]+/[^/]+','id' => '[0-9]+']) It will work just fine (tested with Laravel 5.6). – Arthur Oct 26 '18 at 11:04
  • how is this '(.*)' mean this '/' ? – Yevgeniy Afanasyev Sep 17 '19 at 08:14
10

I have a similar issue but my URL contains several route parameters :

/test/{param1WithSlash}/{param2}/{param3}

And here is how I managed that case :

    Route::get('test/{param1WithSlash}/{param2}/{param3}', function ($param1MayContainsSlash, $param2, $param3) {

        $content = "PATH: " . Request::path() . "</br>";
        $content .= "PARAM1: $param1WithSlash </br>";
        $content .= "PARAM2: $param2 </br>".PHP_EOL;
        $content .= "PARAM3: $param3 </br>".PHP_EOL;

        return Response::make($content);
    })->where('param1MayContainsSlash', '(.*(?:%2F:)?.*)');

Hope it can help.

Pierre
  • 101
  • 1
  • 2
  • Brilliant, thank you! This is working on my end, and also works for multiple parameters each containing one or more slashes. – Matt Rabe Feb 21 '20 at 02:46
  • This must be the accepted answer. This is indeed the standard solution because it is recommended by the Laravel's doc: https://laravel.com/docs/5.1/routing#parameters-regular-expression-constraints – aderchox Nov 19 '20 at 11:41
8

urlencoded slashes do not work in Laravel due to what I consider a bug. https://github.com/laravel/framework/pull/4323 This pull request will resolve that bug.

Update.

Note that the change allows the route to be parsed BEFORE decoding the values in the path.

Artistan
  • 1,982
  • 22
  • 33
7

In Laravel 8+

Route::get('/search/{search}', function ($search) {
    return $search;
})->where('search', '.*');

Reference:

https://laravel.com/docs/routing#parameters-encoded-forward-slashes

usernotnull
  • 3,480
  • 4
  • 25
  • 40
4

I've already upvoted Pierre's answer, it's correct, but in my opinion is longer than needed, here's a very short for-the-impatient sample route that does the trick:

Route::get('post/{slug}', [PostController::class, 'show'])->where('slug', '[\w\s\-_\/]+');

This is all you need. Indeed, the \/ in the regular expression above(in the where method) is all you need !

Now for example:

  • domain/A ---> "A" will be passed to the show method of the PostController.
  • domain/A/B ---> "A/B" will be passed to the show method of the PostController.
  • domain/A/B/C ---> "A/B/C" will be passed to the show method of the PostController.
  • and so on...

For more samples read this: Laravel Documentation - Regular Expression Constraints

aderchox
  • 3,163
  • 2
  • 28
  • 37