Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Woodlandtrek's avatar

Optional route parameters with dependency injection

I've run into an error when upgrading my app to PHP 8.0 and I'm not sure how to fix it. I have a route that loads a page which is generated for the current date by default, but can accept another month and day in the url params and load that instead. In my routes file this looks like:

    $router->get('today/{month?}/{day?}', 'TodayController@index')->name('today.index');

Then in my TodayController I process that with the following:

    public function index(int $month = null, int $day = null, DailystoryRepository $dailystoryRepository, EventRepository $eventRepository ) {
        [$month, $day] = $this->prepareToday($month, $day); //calculates current month # and day #
        $story = $dailystoryRepository->findForDate($month, $day);
        $events = $eventRepository->findForDate($month, $day);
        return view('today.index', compact('story', 'events'));
    }

For the last 5 years this worked fine, but in php 8+ I get an error when I try to load the default page example.com/today (without the day and month parameters)

The error is as follows Argument #1 ($month) must be of type ?int, Chi\Platform\Repositories\DailystoryRepository given

What is the proper way to handle this?

0 likes
4 replies
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

Optional parameters should always come last

1 like
Woodlandtrek's avatar

@jlrdw You're right, it was 8.1 that I was seeing this on. I had switched several back and forth several times in this upgrade and didn't remember where it started.

@sinnbeck I'm still a little confused on how dependency injection works in controller methods, but I guess the solution here is as simple as switching the order. Thanks!

Sinnbeck's avatar

@Woodlandtrek Yeah its a bit tricky :) Route model binding matches on the variable name. So {user} will match User $user. But other routes match the order (like in your case). But as they are optional, php dictates that they must come last, so laravel resolves the injected paramters first, and then your bindings afterwards

1 like

Please or to participate in this conversation.