Los controladores son una parte esencial del framework Laravel, con un controlador podemos agregarle dinamismo a nuestra aplicación ya que nos permite interactuar con modelos y otras clases de nuestra aplicación. En este artículo vamos a resaltar 10 características que no deberíamos olvidar.
Controlador de Recurso (Resource Controller)
Con Laravel crear un controlador que tenga todos los métodos necesarios para un CRUD es muy simple, gracias a la consola interactiva se puede crear con este simple comando:
php artisan make:controller UserController --resource
Además de crear un controlador para un CRUD, se puede asociar el controlador a un modelo añadiendo la opción model al comando anterior de esta forma:
php artisan make:controller UserController --resource --model=User
Para enlazar a estos controladores con todos sus métodos podemos hacerlo de forma simple en nuestras rutas sin tener que definir cada una, para hacerlo debemos usar el método resource:
Route::resource('users', 'UserController');
En el caso de no utilizar algún método en específico, se puede desactivar utilizando el método except y en el caso de que solo queramos utilizar los que especifiquemos, se puede hacer con el método only como se muestra a continuación:
Route::resource('users', 'UserController')->only([
'index', 'show', 'destroy']);
Route::resource('Users', 'UserController')->except (['create', 'store']);
Controladores de un solo método
Si tienes tiempo desarrollando con Laravel te has encontrado con controladores que cumplen una función muy específica, tanto que solo disponen de un método. Para este tipo de ocasiones, Laravel nos permite utilizar el método mágico __invoke de esta forma:
<?php
namespace App\Http\Controllers;
use App\Ticket;
class ShowTicket extends Controller
{
public function __invoke(Ticket $ticket)
{
return view('tickets.show', compact('ticket'));
}
}
Después de ver esto quizás te preguntes cómo podemos especificar el llamado de este método desde nuestras rutas. Pues, el método __invoke será lanzado al intentar llamar a la clase de un controlador sin especificar la acción:
Route::get('ticket/{ticket}', 'ShowTicket');
Métodos para el retorno de redirecciones
Existen algunos helpers muy útiles que pueden ayudarnos con las respuestas, en el caso de las redirecciones tenemos el helper back() el cual retorna una redirección hacia la ruta anterior y lo podemos usar de esta forma tan simple:
public function store(Request $request)
{
User::create($request->all());
return back();
}
Si quieres hacer una simple redirección hacia una dirección específica solo basta con utilizar el helper redirect():
public function store(Request $request)
{
User::create($request->all());
return redirect('/home');
}
Aunque si no te convence especificar rutas estáticas puedes concatenar el método route() y especificar el nombre de una ruta:
public function store(Request $request)
{
User::create($request->all());
return redirect()->route('users.index');
}
Podemos redireccionar hacia un dominio externo con el método away() de la siguiente forma:
public function foo()
{
return redirect()->away('https://www.sitio.net');
}
Redirecciones con mensajes de sesión
Los mensajes en la gran mayoría de los casos son muy importantes ya que le indicamos al usuario que está sucediendo; en Laravel podemos redirigir con algún tipo de mensaje desde el método de un controlador y es tan simple como esto:
public function destroy(User $user)
{
$user->delete();
return back()->with('success', 'Usuario eliminado con éxito.');
}
Con el método with podemos crear un mensaje de sesión temporal o «flash» si indicamos su nombre y su valor, además podemos mostrarlo en la vista de la siguiente forma:
@if (session('success')) // Comprobamos que exista
{{ session('success') }} // Imprimir el contenido indicando el nombre.
@endif
Si especificar el nombre y el valor del mensaje de sesión te parece mucho, existe una forma aun más simple siguiendo esta convención withSuccess el texto remarcado es el nombre del mensaje y como parámetro le pasaríamos el valor, como se puede ver en el siguiente ejemplo:
return back()->withSuccess('Valor del success');
{{ session('success') }} // Valor del success
return back()->withSitio('Sitio.net');
{{ session('sitio') }} // Sitio.net
Respuestas hacia otros métodos de los controladores
Cuando tenemos varios métodos que se repiten existe la posibilidad de responder hacia otro método. Un ejemplo puede ser éste:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
$user = User::create($request->all());
return view('users.show', compact('user'));
}
public function show(User $user)
{
return view('users.show', compact('user'));
}
}
Seguramente ya lo has notado, en el método store luego de guardar el nuevo usuario se repite lo que hace el método show y aunque pueda parecer muy obvio, este caso se puede encontrar muy seguido y no es recomendable. Debido a que si en un futuro necesitas agregar algo de lógica a la vista tendrás que modificar dos métodos, además podrás tener problemas por envío duplicado de datos. La solución para evitar tener que reescribir código es redirigir hacía el método del controlador utilizando el método redirectToAction después del helper response de esta forma:
public function store(Request $request)
{
$user = User::create($request->all());
return response()-> redirectToAction ('UserController@show', $user);
}
El método acepta 4 argumentos, donde obligatoriamente debemos especificarle el controlador y la acción, de forma opcional podemos indicar los parámetros del método que estamos llamando, status y header.
Otros tipos de respuestas
Para responder una vista lo podemos hacer usando el helper view de esta forma:
public function index()
{
$variable = 'valor';
return view('users.index', compact('variable'));
}
El helper view recibe el nombre de la vista, en caso de estar dentro de carpetas debemos especificarlas y usar los puntos, cabe resaltar que no hace falta especificar la extensión de la vista ya que Laravel se encarga de esto. Como segundo argumento recibe un arreglo asociativo donde las llaves serán los nombres de las variables en la vista y los valores serán el contenido de la variable.
La función compact de PHP recibe los nombres de las variables a transformar en un arreglo asociativo, para que quede más claro podemos observar este código:
$variable = 'valor';
$temp = compact('variable');
// El contenido de temp es:
[
'variable' => 'valor'
]
Si estás trabajando sobre un controlador específico para un API puedes tener respuestas de tipo JSON de esta forma:
return response()->json([
'name' => 'Foo Bar',
'website' => 'sitio.net'
]);
Se puede resaltar que, por defecto, el método json configurará automáticamente el encabezado Content-Type a application/json.
Podemos responder descargas directas de archivos con el método download y es muy sencillo:
// Especificamos el path del archivo, el primer argumento es obligatorio, el resto es opcional.
return response()->download($direccionDelArchivo, $nombre, $headers);
// Podemos llamar el método deleteFileAfterSend
// si queremos que sea eliminado el archivo luego de responder.
return response()->download($direccionDelArchivo)->deleteFileAfterSend(true);
Con los métodos anteriores estamos retornando una descarga, pero si quieres una visualización de un archivo como puede ser un PDF o un archivo de texto en el navegador podemos hacerlo con el método file como se muestra a continuación:
// El primer parámetro es obligatorio y el segundo es opcional.
return response()->file($direccionDelArchivo, $headers);
Métodos authorize para los permisos
Con los controladores podemos comprobar los permisos que tenemos sobre algún recurso, para esto tenemos algunos métodos disponibles:
public function update(Request $request, Post $post)
{
// Con este método especificamos la acción y el recurso.
$this->authorize('update', $post);
// Podemos especificar un usuario con este método
$this->authorizeForUser($user, 'update', $post);
}