2

I have the following route in web.php:

Route::get('posts/{encoded_id}/{slug}', 'PostController@show')

... and it works fine:

http://example.test/posts/1Dl89aRjpk/this-is-some-title

But the "problem" is that it will also work when I add a white space at the end of route parameter {encoded_id}:

http://example.test/posts/1Dl89aRjpk /this-is-some-title

// or

http://example.test/posts/1Dl89aRjpk%20 /this-is-some-title

// or

http://example.test/posts/1Dl89aRjpk%20%20 /this-is-some-title

With whitespace added at the end - this will work normally and there is no 404:

Post::where('encoded_id', $encoded_id)->firstOrFail();

... but why? And how can I make it to fail (to give 404)?

Maybe because of the type of field in the DB (CHAR)?

$table->char('encoded_id', 10)

If that's why - is there any way to configure MySQL in databases.php so that it will prevent this?

Or maybe it has something to do with .htaccess (I'm using XAMPP / Windows)?

I'm using Laravel 5.6.

EDIT:

I'm asking why this is happening and how can I prevent it, not how to trim route parameter. For example, add white space at the end of the question id on stackoverflow url and you will get 404:

https://stackoverflow.com/questions/51068436 /laravel-route-parameters-not-trimmed-it-normally-works-when-whitespace-is-added
PeraMika
  • 3,539
  • 9
  • 38
  • 63

2 Answers2

2

This is due to expected SQL behaviour. In your controller you receive the full $encoded_id with spaces. All what Laravel does for you, is calling an SQL select query with WHERE. SQL ignores trailing spaces in WHERE comparison.

See this question.

If you want a 404, replace spaces in the ID to some dummy character:

$encoded_id = str_replace(' ', '#', $encoded_id);

Do this only if it is guaranteed that the ID doesn't contain spaces or hash marks otherwise.

balping
  • 7,518
  • 3
  • 21
  • 35
0

Building on balping's answer. Some other solutions would be:

Replace all trailing spaces with #

preg_replace("/\s+$/", "#", $encoded_id);

Use trim in combination with str_pad and strlen. This will trim the whitespaces from the front and back but pad the string with #'s so it's still the original length.

str_pad(trim($encoded_id), strlen($encoded_id), '#');
Devon Bessemer
  • 34,461
  • 9
  • 69
  • 95