# Controladores de recursos RESTful

Laravel incorpora un tipo especial de controlador, llamado controlador de recuso (*recource controller*), que facilita la construcción de controladores tipo *RESTful*. Para esto simplemente tendríamos que usar el comando de Artisan `php artisan make:controller <nombre-controlador> --resource` para crear el controlador y añadir la ruta al fichero de rutas `routes/web.php` usando `Route::resource`.

Por ejemplo, para crear un controlador para la gestión de imágenes almacenadas en la aplicación, en primer lugar ejecutaríamos el siguiente comando:

```bash
php artisan make:controller PhotoController --resource
```

Esto crearía el controlador `PhotoController` (incluyendo todos los métodos necesarios) en la carpeta `app/Http/Controllers`. Lo único que nos faltaría es registrar las rutas asociadas añadiendo al fichero `routes/web.php` la siguiente línea:

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

Esta línea de ruta crea por si sola múltiples rutas para gestionar todos los tipos de peticiones *RESTful*. Además, el controlador creado mediante Artisan estará preparado con todos los métodos necesarios para responder a todas las peticiones correspondientes. En la siguiente tabla se muestra un resumen de todas las rutas generadas, el tipo de petición a la que responden y la acción que realizan en el controlador:

| Verbo     | Ruta                   | Acción  | Controlador / método     |
| --------- | ---------------------- | ------- | ------------------------ |
| GET       | /photo                 | index   | PhotoController\@index   |
| GET       | /photo/create          | create  | PhotoController\@create  |
| POST      | /photo                 | store   | PhotoController\@store   |
| GET       | /photo/{resource}      | show    | PhotoController\@show    |
| GET       | /photo/{resource}/edit | edit    | PhotoController\@edit    |
| PUT/PATCH | /photo/{resource}      | update  | PhotoController\@update  |
| DELETE    | /photo/{resource}      | destroy | PhotoController\@destroy |

## Restringir rutas en un controlador RESTful

En ocasiones nos interesará declarar solamente un subconjunto de las acciones que soporta REST, para esto, al declarar la ruta tipo `resource` tenemos que añadir un tercer parámetro con la opción `only` (para que solo se creen esas rutas) o `except` (para que se creen todas las rutas excepto las indicadas), por ejemplo:

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

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

Los métodos que no utilicemos los podremos borrar del código generado para el controlador.

## Rutas adicionales en un controlador tipo RESTful

Si queremos definir rutas adicionales para un controlador de recursos simplemente las tenemos que añadir al fichero de rutas `routes/web.php` antes que las rutas del propio recurso, por ejemplo:

```php
Route::get('photos/popular', 'PhotoController@getPopular');
Route::resource('photos', 'PhotoController');
```

## Middleware

Para añadir *middleware* a un controlador tipo recurso tenemos dos opciones. La primera es definir un grupo que lo englobe, por ejemplo:

```php
Route::group(['middleware' => 'auth'], function() {
    Route::resource('photo', 'PhotoController');
});
```

La otra opción es definir el *middleware* en el constructor del controlador de la forma:

```php
class PhotoController extends Controller {
    public function __construct() {
        $this->middleware('auth');
        $this->middleware('log', ['only' => ['store', 'update', 'destroy']]);
    }
}
```

## Definir una API mediante controladores RESTful

Si queremos definir una API, ya sea mediante controladores tipo RESTful o controladores normales, es recomendable que utilicemos el fichero de rutas `routes/api.php` en lugar de `routes/web.php`. En este fichero las rutas se definen exactamente de la misma forma que hemos estado viendo hasta ahora, usando la clase `Route`, los métodos `get`, `post`, `put` y `delete`, los controladores de recursos, los grupos de rutas, *middleware*, parámetros, etc. Además, al ejecutar el comando `php artisan route:list` estas rutas aparecerán en el mismo listado. Por lo que... ¿en qué se diferencian? Las diferencias entre estos ficheros de rutas son dos:

* Los filtros o *middleware* que se utilizan: Mientras que en `routes/web.php` se aplican filtros para inicializar la sesión, las cookies, los *bindings* y la protección CSRF; en las rutas que se añadan a `routes/api.php` únicamente se aplican filtros para limitar el número de peticiones y para cargar los *bindings* (la inyección de dependencias). Esto lo podemos ver si editamos el fichero `app/Http/Kernel.php`, donde dentro de su array `$middlewareGroups` veremos dos grupos: `web` y `api`, con los filtros que se aplican en cada caso.&#x20;
* El prefijo de las rutas: A todas las rutas que especifiquemos en `routes/api.php` se les añadirá el prefijo `api`. Por lo que si añadimos la ruta `users` para devolver el listado de usuarios, para realizar la consulta tendremos que acceder a `api/users`. Esto lo podemos comprobar en el listado de rutas que muestra Artisan.&#x20;

Estas diferencias aportan varias ventajas, por un lado tenemos separadas todas las rutas de la API tanto en un fichero distinto como por un prefijo, por lo que no se mezclarán los distintos tipos de rutas de nuestro sitio web. Además, las peticiones a las rutas de la API no tienen que cargar *middleware* innecesario, permitiéndonos también definir otros filtros propios de una API, como el de *rate limit*. Las peticiones a estas rutas no mantendrán sesión, por lo tanto se tendrán que autenticar bien mediante *tokens* o mediante seguridad HTTP básica (usando las cabeceras de la petición). Además, en las respuestas no tendremos que devolver una vista (con HTML), sino directamente el dato o la lista de datos solicitados en formato plano, en XML o en JSON.

En las siguientes secciones veremos cómo probar las rutas de una API, cómo protegerlas mediante autenticación HTTP básica y cómo devolver contenido correctamente formateado.
