I have been using RESTful controllers in my Laravel project. By including:
Route::controller('things', 'ThingController')
in my routes.php, I can define functions in the ThingController
like:
public function getDisplay($id) {
$thing = Thing::find($id)
...
}
so that GETting the URL "...things/display/1" would automatically be directed to the controller function. This seems pretty handy and has been working great for me so far.
I noticed many of my controller functions start with getting a model by id from the url, and I thought it would be nice to be able to use route model binding to do this for me instead. So I updated my routes.php to
Route::model('thing', 'Thing');
Route::controller('things', 'ThingController')
and changed the ThingController
functions to
public function getDisplay($thing) {
...
}
I assumed this would magically work the way I wanted it to (like everything else I've tried so far in Laravel has) but unfortunately I get "Trying to get property of non-object" when I attempt to use $thing
in the function. Is this something that should be able to work and I have just done it wrong, or can route model binding only work with routes explicitly named in routes.php?
If you don't mind with URI path, method name and just work only show
, edit
and update
method, you can use Resource Controller to generate URI string which can define model binding.
In routes.php
change to
Route::model('things', 'Thing');
Route::resource('things', 'ThingController');
You can use php artisan routes
command to see all URIs
$ artisan routes | grep ThingController
GET|HEAD things | things.index | ThingController@index
GET|HEAD things/create | things.create | ThingController@create
POST things | things.store | ThingController@store
GET|HEAD things/{things} | things.show | ThingController@show
GET|HEAD things/{things}/edit | things.edit | ThingController@edit
PUT things/{things} | things.update | ThingController@update
PATCH things/{things} | | ThingController@update
After that you can threat parameter as Thing
object without explicitly name route.
/**
* Display the specified thing.
*
* @param Thing $thing
* @return mixed
*/
public function show(Thing $thing)
{
return $thing->toJson();
}
If you want to access ThingController@show
, pass your model ID and Laravel will retrieve it automatically.
http://example.com/things/1
{"id":1,"type":"Yo!"}
You can use Route:resource and still provide other methods. Place the route you need just before that particular Route::resource
line.
Eg:
Route::model('things', 'Thing');
Route::get('things/{things}/owner', 'ThingController@getOwner');
Route::resource('things', 'ThingController');
Then create the corresponding method in your controller.
public function getOwner($things) {
return Response::json($things->owner()->get());
}
Here is the official documentation from the Laravel 4.2 docs:
Source: http://laravel.com/docs/controllers#resource-controllers
Adding Additional Routes To Resource Controllers
If it becomes necessary for you to add additional routes to a resource controller beyond the default resource routes, you should define those routes before your call to Route::resource
:
Route::get('photos/popular');
Route::resource('photos', 'PhotoController');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With