IainChambers
IainChambers

Reputation: 388

Laravel dependency injection not working

I'm using resource controllers in my laravel app and I'm trying to use dependancy injection but it's not working on a particular model and controller.

This works:

/**
* Display the specified resource.
*
* @param  \App\Booking  $booking
* @return \Illuminate\Http\Response
*/
public function show(Booking $booking)
{
    return $booking;
}

But for some infuriating reason this doesn't:

/**
 * Display the specified resource.
 *
 * @param  \App\SchoolEvent  $schoolEvent
 * @return \Illuminate\Http\Response
 */
public function show(SchoolEvent $schoolEvent)
{
    return $schoolEvent;
}

My Routes look like this:

// Events
Route::resource('events', Resources\SchoolEventController::class);

// Bookings
Route::resource('bookings', Resources\BookingController::class);

For some reason /bookings/1 returns a filled object but /events/1 returns an empty one. Can anyone tell me why?

Upvotes: 14

Views: 8603

Answers (4)

dparoli
dparoli

Reputation: 9161

Change the injected variable name to $event to match the route parameter name {event}:

public function show(SchoolEvent $event)

You can see the route parameters with this command:

php artisan route:list

Upvotes: 28

When you use Route::resource, this will automatically generate all routes and the name for parameters that comes into each route.

To know what is the name, run php artisan route:list at your terminal. After that you will see the name that each route is waiting. Use this name into your Controller.

In your case, probably will be $school_event.

If you doesn't like the name you can use parameters function like this:

Route::resource(**'events'**, Resources\SchoolEventController::class)
    ->parameters([
        **'events'** => 'here_the_name_you_want'
]);

Work on Laravel 5.5!

Reference: https://laravel.com/docs/5.5/controllers#restful-naming-resource-route-parameters

Upvotes: 0

Cee Kay
Cee Kay

Reputation: 11

There is another possible solution.

As has been explained Laravel tries to inject an instance, but there is a mismatch between the URI segment name and the variable.

Laravel allows to explicitly bind a Model to a slug in the RouteServiceProvider within the boot() method.

In your case:

public function boot()
{
   parent::boot();

   // binds the slug event to our SchoolEvent model
   Route::model('event', \App\SchoolEvent::class);
}

See: https://laravel.com/docs/5.4/routing#explicit-binding

I feel both solutions are viable, but personally prefer this one. All non-default slugs are in one place rather than in the individual controllers and I keep using artisan to quickly generate the basic controller code.

Upvotes: 1

Alexey Mezenin
Alexey Mezenin

Reputation: 163768

Change the model name to Event to make model binding work.

Since the $user variable is type-hinted as the App\User Eloquent model and the variable name matches the {user} URI segment, Laravel will automatically inject the model instance that has an ID matching the corresponding value from the request URI

Upvotes: 5

Related Questions