Controladores HTTP

Introducción

En lugar de definir toda la lógica de tus peticiones en un único archivo routes.php, puedes organizar el comportamiento de tu aplicación utilizando clases controladoras. Los controladores pueden agrupar en una clase la lógica de distintas peticiones HTTP relacionadas. Los controladores se almacenan normalmente en el directorio App/Http/controladores.

Controladores básicos

Here is an example of a basic controller class. All Laravel controllers should extend the base controller class included with the default Laravel installation:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

Podemos enrutar hacia la acción de un controlador así:

Route::get('user/{id}', 'UserController@showProfile');

Now, when a request matches the specified route URI, the showProfile method on the UserController class will be executed. Of course, the route parameters will also be passed to the method.

Controladores & namespaces

It is very important to note that we did not need to specify the full controller namespace when defining the controller route. We only defined the portion of the class name that comes after the App\Http\Controllers namespace "root". Por defecto, el service provider RouteServiceProvider cargará el archivo routes.php dentro de un grupo de rutas que contiene el namespace raíz del controlador.

Si eliges anidar u organizar tus controladores utilizando namespaces de PHP en un nivel más interno que el directorio App\Http\Controllers, simplemente usa el nombre específico de la clase relativo al namespace App\Http\Controllers. Por lo que, si tu controlador está en App\Http\Controllers\Photos\AdminController, registrarías la ruta así:

Route::get('foo', 'Photos\AdminController@method');

Nombrando rutas a controladores

Como las rutas a Closures, puedes especificar nombres en rutas a controladores:

Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);

Once you have assigned a name to the controller route, you can easily generate URLs to the action. To generate a URL to a controller action, use the action helper method. Again, we only need to specify the part of the controller class name that comes after the base App\Http\Controllers namespace:

$url = action('FooController@method');

You may also use the route helper to generate a URL to a named controller route:

$url = route('name');

Middleware en controladores

Middleware may be assigned to the controller's routes like so:

Route::get('profile', [
    'middleware' => 'auth',
    'uses' => 'UserController@showProfile'
]);

However, it is more convenient to specify middleware within your controller's constructor. Using the middleware method from your controller's constructor, you may easily assign middleware to the controller. You may even restrict the middleware to only certain methods on the controller class:

class UserController extends Controller
{
    /**
     * Instantiate a new UserController instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');

        $this->middleware('log', ['only' => ['fooAction', 'barAction']]);

        $this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
    }
}

Controladores de Recursos RESTful

Los controladores de recursos hacen que sea más sencilla la creación de controladores RESTful sobre recursos. Por ejemplo, quizás quieras crear un controlador que maneje peticiones HTTP sobre "fotos" almacenadas por tu aplicación. Usando el comando de Artisan make:controller, podemos crear un controlador de este tipo:

php artisan make:controller PhotoController

The Artisan command will generate a controller file at app/Http/Controllers/PhotoController.php. The controller will contain a method for each of the available resource operations.

Next, you may register a resourceful route to the controller:

Route::resource('photo', 'PhotoController');

Esta única declaración de ruta crea múltiples rutas para manejar una variedad de métodos RESTful para el recurso "photo". Asimismo, el controlador generado ya tendrá métodos para cada una de estas acciones, incluyendo las notas informando que URIs y verbos maneja.

Acciones controladas por un controlador de recursos

Verbo Ruta de acceso Acción Nombre de ruta
GET /photo index photo.index
GET /photo/create create photo.create
POST /photo store photo.store
GET /photo/{photo} show photo.show
GET /photo/{photo}/edit edit photo.edit
PUT/PATCH /photo/{photo} update photo.update
DELETE /photo/{photo} destroy photo.destroy

Partial Resource Routes

When declaring a resource route, you may specify a subset of actions to handle on the route:

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

Route::resource('photo', 'PhotoController',
                ['except' => ['create', 'store', 'update', 'destroy']]);

Naming Resource Routes

Por defecto, todas las acciones de los controladores de recursos tienen un nombre de ruta; sin embargo, puedes reemplazar estos nombres pasando un array de nombres con tus opciones:

Route::resource('photo', 'PhotoController',
                ['names' => ['create' => 'photo.build']]);

Nested Resources

Sometimes you may need to define routes to a "nested" resource. For example, a photo resource may have multiple "comments" that may be attached to the photo. Para "anidar" controladores de recursos, usa la notación "punto" en la declaración de la ruta:

Route::resource('photos.comments', 'PhotoCommentController');

Esta ruta registrará un recurso "anidado" al que se puede acceder con URLs como la siguiente: photos/{photos}/comments/{comments}.

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class PhotoCommentController extends Controller {

    /**
     * Show the specified photo comment.
     *
     * @param  int  $photoId
     * @param  int  $commentId
     * @return Response
     */
    public function show($photoId, $commentId)
    {
        //
    }

}

Supplementing Resource Controllers

If it becomes necessary to add additional routes to a resource controller beyond the default resource routes, you should define those routes before your call to Route::resource; otherwise, the routes defined by the resource method may unintentionally take precedence over your supplemental routes:

Route::get('photos/popular', 'PhotoController@method');

Route::resource('photos', 'PhotoController');

Controladores implícitos

Laravel allows you to easily define a single route to handle every action in a controller class. First, define the route using the Route::controller method. El método controller acepta dos argumentos. The first is the base URI the controller handles, while the second is the class name of the controller:

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

Next, just add methods to your controller. The method names should begin with the HTTP verb they respond to followed by the title case version of the URI:

<?php

namespace App\Http\Controllers;

class UserController extends Controller
{
    /**
     * Responds to requests to GET /users
     */
    public function getIndex()
    {
        //
    }

    /**
     * Responds to requests to GET /users/show/1
     */
    public function getShow($id)
    {
        //
    }

    /**
     * Responds to requests to GET /users/admin-profile
     */
    public function getAdminProfile()
    {
        //
    }

    /**
     * Responds to requests to POST /users/profile
     */
    public function postProfile()
    {
        //
    }
}

As you can see in the example above, index methods will respond to the root URI handled by the controller, which, in this case, is users.

Asignación de nombres de ruta

If you would like to name some of the routes on the controller, you may pass an array of names as the third argument to the controller method:

Route::controller('users', 'UserController', [
    'getShow' => 'user.show',
]);

Inyección de dependencias & controladores

Inyección en el constructor

The Laravel service container is used to resolve all Laravel controllers. As a result, you are able to type-hint any dependencies your controller may need in its constructor. The dependencies will automatically be resolved and injected into the controller instance:

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * Crear una nueva instancia del controlador.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}

Of course, you may also type-hint any Laravel contract. If the container can resolve it, you can type-hint it.

Inyección en métodos

In addition to constructor injection, you may also type-hint dependencies on your controller's action methods. For example, let's type-hint the Illuminate\Http\Request instance on one of our methods:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->input('name');

        //
    }
}

If your controller method is also expecting input from a route parameter, simply list your route arguments after your other dependencies:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * Update the specified user.
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }
}

Caché de rutas

If your application is exclusively using controller based routes, you may take advantage of Laravel's route cache. El uso del caché reduce drásticamente la cantidad de tiempo que se tarda en registrar todas las rutas de tu aplicación. En algunos casos, ¡puede llegar a ser hasta 100 veces más rápido! Para generar un caché de rutas, simplemente ejecuta el comando Artisan route:cache:

php artisan route:cache

¡Eso es todo! Ahora se utilizarán las rutas en caché en vez de las rutas en tu archivo app/Http/routes.php. Recuerda que si añades nuevas rutas, deberás generar un nuevo caché de rutas. Por esta razón, es recomendable ejecutar el comando route:cache sólo en la producción de tu proyecto.

Para quitar el archivo de caché de rutas sin generar un nuevo caché, utiliza el comando route:clear:

php artisan route:clear