When using Artisan to generate a model (and resource controller) with multiple words, the route param doesn't match the var names used in the controller.
The route param ends up snake case, while the var names are camel case.
artisan make:model -mcr ProductionOrder
// routes/web.php
Route::resource('production-orders', 'ProductionOrderController');
// app/ProductionOrder.php (generated by Artisan)
public function show(ProductionOrder $productionOrder) {};
// wherever.php
dd(Route::getRoutes());
// #allRoutes: array:8 [
// "HEADapi/user" => Illuminate\Routing\Route {#250}
// "HEADproduction-orders" => Illuminate\Routing\Route {#240}
// "HEADproduction-orders/create" => Illuminate\Routing\Route {#239}
// "POSTproduction-orders" => Illuminate\Routing\Route {#238}
// "HEADproduction-orders/{production_order}" => Illuminate\Routing\Route {#237}
// "HEADproduction-orders/{production_order}/edit" => Illuminate\Routing\Route {#236}
// "PATCHproduction-orders/{production_order}" => Illuminate\Routing\Route {#235}
// "DELETEproduction-orders/{production_order}" => Illuminate\Routing\Route {#234}
// ]
Yes i have this problem too, this issue is valid.
Is there a problem with it not working or is it just the url formatting thats not fitting you? :)
URL formatting has nothing to do with it. It's the param being passed as {production_order} while the controller expects productionController.
I did learn a workaround:
Route::resource('production-orders', 'ProductionOrderController', [
'parameters' => ['production-orders' => 'productionOrder']
]);
However, this is still a :bug:.
Why not
Route::resource('productionOrders', 'ProductionOrderController');
and everything just works as it should
if i remember correctly you should be able to name the variable anything you want you dont have to keep the snakeCase version, you should be able to name it foo and still have the same value
@stefanoruth I think the same, but it's failing when you 'bind' it to the model.
just try it,
php artisan make:model ProductOrder -m -c -r
boom, it generate method like
public function show(ProductOrder $productOrder)
there where it goes failing the argument is just null value.
but if I change it to
publiic function show(ProductOrder $product_order)
It works. of course if I change it without bind it like
public function show($a)
, it also works, but $a is string not a model.
I think the problem is in artisan generation. (not only show method).
And this problem only if you generate model with -m -c -r flag. If you do it separately it works fine.
@curtisblackwell Btw, i prefer underscore instead of dash. Seems like underscore is Laravel default. :smile_cat:
@devcircus 鈥ecause it doesn't work as it should. See the first post.

@stefanoruth Yes, you can rename it, but the point of Artisan is to make things more convenient. It doesn't just work when model names are multi-word in camel case.
As someone new to building Laravel apps, this is pretty confusing. It took me a long time to track down the problem, and even asking a more experienced Laravel dev was no help. Should be an easily-prevented problem. It's obviously a simple mistake made when writing the code. No way whomever wrote it intentionally set something to send snake case but receive camel case.
I understand the issue, I guess I've just never thought of snake casing my resource routes. So for me, it's always worked perfectly, as I use:
Route::resource('productionOrders', 'ProductionOrderController');
Maybe dig into the source and submit a PR to make it work the way you use it.
The first argument is used for the slug, though. Odd to use camel case there.
I do plan to submit a PR at some point, but I don't have the time to figure everything out now. Given I'll likely encounter this on every app, I'm sure I won't forget.
Laravel magically will inject a initiated ProductOrder model with the id given in the url at the placeholder:
{production_order} .
https://laravel.com/docs/5.4/controllers#resource-controllers
Naming Resource Route Parameters
By default, Route::resource will create the route parameters for your resource routes based on the "singularized" version of the resource name. You can easily override this on a per resource basis by passing parameters in the options array. The parameters array should be an associative array of resource names and parameter names:
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
The example above generates the following URIs for the resource's show route:
/user/{admin_user}
Has this been fixed? I was just looking at some loosely related bugs and tried to reproduce this but (with Laravel 5.5.2) it seems to work as expected. Can anyone else confirm?
I'm seeing no change. Resource route still passes snake-cased variable name, and Artisan-generated controller still expects camelcase.
Just tried this in response to a Laracasts thread.
Making model and controller as php artisan make:model -mcr WorkRequest creates controller methods expecting to be passed $workRequest
The fix appears to be to specify the route with snake case
Route::resource('work_requests', 'WorkRequestController');
This causes the route to expect {work_request} which gets passed to the controller as $workRequest and matches the variables in the artisan generated resource controller
In addition to snapey's answer, you can also use dashes in the resource method and it'll work just as usual.
Route::resource('my-route'), 'RouteController');
Route will expect {my_route} and controller will expect (MyRoute $myRoute) but it'll work as usual. Seems like this is a new fix, since it didnt use to work.
Most helpful comment
In addition to snapey's answer, you can also use dashes in the resource method and it'll work just as usual.
Route::resource('my-route'), 'RouteController');Route will expect
{my_route}and controller will expect(MyRoute $myRoute)but it'll work as usual. Seems like this is a new fix, since it didnt use to work.