72

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.

5 Answers 5

143

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 ]

Sign up to request clarification or add additional context in comments.

5 Comments

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.
It works similar in Lumen $app->get('/documents/{document:.+}', 'DocumentController@show');
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!
@Chistopher K. you can accept slash parameters perfectly just don't use url encoding on the slash; that is a separate bug in Laravel (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).
how is this '(.*)' mean this '/' ?
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.

2 Comments

Brilliant, thank you! This is working on my end, and also works for multiple parameters each containing one or more slashes.
This must be the accepted answer. This is indeed the standard solution because it is recommended by the Laravel's doc: laravel.com/docs/5.1/…
9

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.

2 Comments

bug fix denied so I wrote a package... github.com/Artistan/Urlencode
It definitely is a bug, and it bit me again today in Laravel 10 (last time was about 5 years ago). More specifically, it looks like some conceptual problem. It seems like a related issue that e. g. route('search', 'LED (red/green)') returns "example.com/search/LED%20%28red/green%29", where spaces and brackets are encoded, but not the slash. There has to be some reasoning behind that.
9

In Laravel 8+

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

Reference:

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

1 Comment

Ah! The power of proper documentation!
5

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.