Laravel 4 defining RESTful controllers

Iain picture Iain · Aug 23, 2013 · Viewed 17.3k times · Source

So I'm new to the Laravel framework as of v4 and wondering what is the way to create and use RESTful controllers. Reading through the documentation, I'm a bit confused as to the difference between RESTful controllers and Resource controllers.

When defining a RESTful controller, as per the docs, it suggests doing the following in routes.php:

Route::controller('posts', 'PostController');

In the PostController, do we define the class methods by prefixing the name of the method with the HTTP verb we should like to use? For example:

class PostController extends \BaseController {
    public function getIndex()
    {
        //
    }
}

However, it also outlines a way of creating Resource controllers in the routes.php file like so: Route::resource('posts', 'PostController');

And in PostController.php we define methods without prefixing it with the HTTP verb.

class PostController extends \BaseController {
    public function index()
    {
        //
    }
}

What is the difference between the two? And when do we use one instead of the other, and why?

Also, should we use Route::controller('posts', 'PostController'); or Route::resource('posts', 'PostController'); to pass routing to the controller or should we define each route manually, like below:

Route::get('/users', 'UserController@index');
Route::get('/users/create', 'UserController@create');
Route::post('/users', 'UserController@store');
Route::get('/users/{id}', 'UserController@show');
Route::get('/users{id}/edit', 'UserController@edit');
Route::put('/users', 'UserController@update');
Route::delete('/users', 'UserController@destroy');

Answer

Antonio Carlos Ribeiro picture Antonio Carlos Ribeiro · Aug 23, 2013

Take this controller as example:

<?php

class TestController extends BaseController {

    public function getIndex()
    {
        echo "a";
    }

    public function postSecond($a)
    {
        echo "b";
    }

}

In your routes, if you have

Route::controller('tests', 'TestController');

And execute

php artisan routes

You'll have:

+--------+--------------------------------------------+------------------------+-----------------------------------+----------------+---------------+
| Domain | URI                                        | Name                   | Action                            | Before Filters | After Filters |
+--------+--------------------------------------------+------------------------+-----------------------------------+----------------+---------------+
|        | GET /tests/index/{v1}/{v2}/{v3}/{v4}/{v5}  |                        | TestController@getIndex           |                |               |
|        | GET /tests                                 |                        | TestController@getIndex           |                |               |
|        | POST /tests                                | tests.store            | TestController@store              |                |               |
|        | GET /tests/{_missing}                      |                        | TestController@missingMethod      |                |               |
+--------+--------------------------------------------+------------------------+-----------------------------------+----------------+---------------+

Laravel inspects the controller and generates routes based on what methods it finds, automatically.

But if you do

Route::resource('tests', 'TestController');

You'll get this route listing:

+--------+--------------------------------------------+------------------------+-----------------------------------+----------------+---------------+
| Domain | URI                                        | Name                   | Action                            | Before Filters | After Filters |
+--------+--------------------------------------------+------------------------+-----------------------------------+----------------+---------------+
|        | GET /tests                                 |                        | Closure                           |                |               |
|        | GET /tests                                 | tests.index            | TestController@index              |                |               |
|        | GET /tests/create                          | tests.create           | TestController@create             |                |               |
|        | POST /tests                                | tests.store            | TestController@store              |                |               |
|        | GET /tests/{tests}                         | tests.show             | TestController@show               |                |               |
|        | GET /tests/{tests}/edit                    | tests.edit             | TestController@edit               |                |               |
|        | PUT /tests/{tests}                         | tests.update           | TestController@update             |                |               |
|        | PATCH /tests/{tests}                       |                        | TestController@update             |                |               |
|        | DELETE /tests/{tests}                      | tests.destroy          | TestController@destroy            |                |               |
+--------+--------------------------------------------+------------------------+-----------------------------------+----------------+---------------+

No guessing, Laravel uses a predefined CRUD list of routes, you can remove some of those routes but it won't inspect your controller to build routes for your methods.

You decide what's best for you. But, usually, if your controller is a CRUD one, Route::resource() is a good start, otherwhise you can use Route::controller() or build your routes manually.

EDIT:

There no really why one or why another, is just a matter of design and choice. Some will use none of them, ever. It's just hat Route::resource() follows the Rails way of routing: http://guides.rubyonrails.org/routing.html.

Using Route::resource() you don't need to create all those methods, but you'll end up with a list of pointless routes, because Laravel always create all of them by default, unless you do:

Route::resource('photo', 'PhotoController',
                array('only' => array('index', 'show')));

And your list of routes will show only the index and show actions.

Also, if you need some other routes, using Route::resource() you'll have to build them manually or work some magic to make them automatic for all your resourceful routes. Using Route::controller() everything is automatic, everytime you add a new method, a new route is created for you.

Again, if you have a CRUD controller to build, start by using Route::resource(). Otherwise, think about the benefits of one or another in your particular case.

EDIT2:

This is a great article, from Phil Sturgeon (PyroCMS and PHP-FIG), about the benefits of manually build all your routes: http://philsturgeon.co.uk/blog/2013/07/beware-the-route-to-evil.