The "correct" answer for this question is; No, you can't and shouldn't use an optional parameter unless it's at the end of the route/url.
But, if you absolutely need to have an optional parameter in the middle of a route, there is a way to achieve that. It's not a solution I would recommend, but here you go:
routes/web.php:
// Notice the missing slash
Route::get('/test/{id?}entities', 'Pages\TestController@first')
->where('id', '([0-9/]+)?')
->name('first');
Route::get('/test/entities', 'Pages\TestController@second')
->name('second');
app/Http/Controllers/Pages/TestController.php:
<?php
namespace App\Http\Controllers\Pages;
use App\Http\Controllers\Controller;
class TestController extends Controller
{
public function first($id = null)
{
// If $id is not null, it will have a trailing slash
$id = rtrim($id, '/');
return 'First route with: ' . $id;
}
public function second()
{
return 'Second route';
}
}
resources/views/test.blade.php:
<!-- Notice the trailing slash on id -->
<!-- Will output http://myapp.test/test/123/entities -->
<a href="{{ route('first', ['id' => '123/']) }}">
First route
</a>
<!-- Will output http://myapp.test/test/entities -->
<a href="{{ route('second') }}">
Second route
</a>
Both links will trigger the first-method in TestController. The second-method will never be triggered.
This solution works in Laravel 6.3, not sure about other versions. And once again, this solution is not good practice.