Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4 defining RESTful controllers

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');
like image 945
Iain Avatar asked Aug 23 '13 11:08

Iain


2 Answers

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.

like image 89
Antonio Carlos Ribeiro Avatar answered Oct 30 '22 14:10

Antonio Carlos Ribeiro


@Antonio's answer is good. Let me say something similar and important a little more concisely. In routes.php:

Route::resource('users', 'UserController');

Using the resource method makes Laravel assume CRUD functionality and it only looks for its six, pre-made CRUD methods: index, create, store, show, destroy, etc. It won't "see" any other, new methods you create there.

Route::controller('info', 'InfoController');

Using the controller method allows you to create custom methods/pages. Laravel looks for them when you prepend the method/page name with a HTTP verb. In your XxxxController.php:

class InfoController extends \BaseController {

    public function getFeatures()
    {
        return View::make('info.features');
    }

    public function getContactUs()
    {
        return View::make('info.contact-us');
    }

    public function getPricing()
    {
        return View::make('info.pricing');
    }

}
like image 22
Andrew Koper Avatar answered Oct 30 '22 16:10

Andrew Koper