ChronoFish
ChronoFish

Reputation: 3707

Laravel Model not binding in controller method

I have a Laravel model PurhaseOrder and a controller PurchaseOrdersController with a method show

If I typecast the method with an an interger:

public function show(int $purchaseOrder)
{
        dd(PurchaseOrder::find($purchaseOrder));
}

Then dd() dumps out what I expect ( the record in the database where the id matches $purchaseOrder)

However if instead I do this:

public function show(PurchaseOrder $purchaseOrder)
{
        dd($purchaseOrder);
}

Then $purchaseOrder is an empty model and not populated with any data from the database. My route looks like this:

Route::get('purchase-orders/{purchase_orders}/show', ['as' => 'admin.purchase-orders.show', 'uses' => 'PurchaseOrdersController@show']);

This is code that I've inherited and I'm trying to update from Laravel 5.3 to Laravel 5.6. Where should I be looking to solve this issue of the model not being populated correctly?

Upvotes: 6

Views: 3040

Answers (1)

The Alpha
The Alpha

Reputation: 146269

The implicit model binding requires you to match the variable name with the route parameter name, so for example, for the following method:

public function show(PurchaseOrder $purchaseOrder)
{
    dd($purchaseOrder);
}

The route should contain the matching parameter name, for example:

Route::get('purchase-orders/{purchaseOrder}/show', [
    'as' => 'admin.purchase-orders.show',
    'uses' => 'PurchaseOrdersController@show'
]);

Notice that, the method parameter name in show method which is $purchaseOrder and the route parameter name {purchaseOrder} both are same and that's a requirement for the implicit model binding, otherwise you have to do an explicit model binding, where you've to explicitly tell the framework about your parameter name, for example (in RouteServiceProvider):

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

    Route::model('purchase_orders', App\PurchaseOrder::class);
}

This will tell the framework that, if there is the {purchase_orders} parameter name available in the route then resolve/bind an instance of PurchaseOrder model into the given method for that route.

Upvotes: 18

Related Questions