Reputation: 3707
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
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