4. Controladores en Laravel
Controladores en Laravel
Section titled “Controladores en Laravel”Los controladores son una parte fundamental de la arquitectura MVC (Modelo-Vista-Controlador) de Laravel. Permiten organizar la lógica de tu aplicación en clases y separar las responsabilidades, haciendo que tu código sea más mantenible y escalable.
En lugar de definir toda la lógica de manejo de solicitudes en los archivos de rutas, los controladores permiten agrupar la lógica relacionada en clases. Los controladores se almacenan en el directorio
app/Http/ControllersCrear un controlador (make:controller)
Section titled “Crear un controlador (make:controller)”Laravel proporciona un comando Artisan para generar rápidamente controladores. Este comando crea un nuevo archivo de controlador con la estructura básica ya definida.
Controlador básico
Section titled “Controlador básico”Para crear un controlador básico, ejecuta el siguiente comando en la terminal:
php artisan make:controller UsuarioControllerEste comando creará un nuevo archivo
UsuarioController.phpapp/Http/Controllers<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
class UsuarioController extends Controller{ //}Controlador en subdirectorio
Section titled “Controlador en subdirectorio”Puedes organizar tus controladores en subdirectorios especificando la ruta relativa en el comando:
php artisan make:controller Admin/ProductoControllerEste comando creará el controlador en
app/Http/Controllers/Admin/ProductoController.phpControlador con opciones adicionales
Section titled “Controlador con opciones adicionales”El comando
make:controllerPara crear un controlador optimizado para APIs:
php artisan make:controller API/ProductoController --apiEsto generará un controlador con métodos para index, store, show, update y destroy, sin métodos para mostrar formularios.
Para crear un controlador con un solo método
__invoke()php artisan make:controller EnviarCorreoController --invokableEsto es útil para controladores que realizan una sola acción.
Para crear un controlador vinculado a un modelo:
php artisan make:controller ProductoController --model=ProductoEsto importará automáticamente el modelo especificado y generará sugerencias de tipo en los métodos del controlador.
Métodos dentro del controlador
Section titled “Métodos dentro del controlador”Los controladores pueden contener cualquier número de métodos públicos que respondan a las solicitudes HTTP. Estos métodos reciben y procesan las solicitudes, interactúan con los modelos y devuelven respuestas.
Estructura básica de un método
Section titled “Estructura básica de un método”Un método típico de controlador tiene la siguiente estructura:
public function show($id){ // Lógica para obtener datos $usuario = Usuario::find($id);
// Devolver una respuesta (vista, JSON, redirección, etc.) return view('usuarios.show', ['usuario' => $usuario]);}Acceder a la solicitud HTTP
Section titled “Acceder a la solicitud HTTP”Puedes acceder a la solicitud HTTP actual mediante la inyección de dependencias de la clase
Requestuse IlluminateHttpRequest;
public function store(Request $request){ // Acceder a los datos del formulario $nombre = $request->input('nombre');
// O usando la sintaxis de array $email = $request['email'];
// Validar datos $validated = $request->validate([ 'nombre' => 'required|string|max:255', 'email' => 'required|email|unique:usuarios' ]);
// Crear un nuevo registro $usuario = Usuario::create($validated);
// Redireccionar return redirect()->route('usuarios.show', ['id' => $usuario->id]);}Métodos comunes en controladores
Section titled “Métodos comunes en controladores”Los controladores suelen seguir convenciones de nomenclatura para sus métodos, especialmente cuando se trabaja con recursos:
| Método | Descripción | Verbo HTTP | Ruta típica |
|---|---|---|---|
| Mostrar listado de recursos | GET | /usuarios |
| Mostrar formulario de creación | GET | /usuarios/create |
| Almacenar nuevo recurso | POST | /usuarios |
| Mostrar un recurso específico | GET | /usuarios/{id} |
| Mostrar formulario de edición | GET | /usuarios/{id}/edit |
| Actualizar un recurso | PUT/PATCH | /usuarios/{id} |
| Eliminar un recurso | DELETE | /usuarios/{id} |
| Método | Descripción | Verbo HTTP | Ruta típica |
|---|---|---|---|
| Listar recursos | GET | /api/usuarios |
| Crear recurso | POST | /api/usuarios |
| Obtener un recurso | GET | /api/usuarios/{id} |
| Actualizar recurso | PUT/PATCH | /api/usuarios/{id} |
| Eliminar recurso | DELETE | /api/usuarios/{id} |
Ejemplo completo de un controlador
Section titled “Ejemplo completo de un controlador”Aquí hay un ejemplo de un controlador completo para gestionar usuarios:
<?php
namespace AppHttpControllers;
use AppModelsUsuario;use IlluminateHttpRequest;use IlluminateSupportFacadesHash;
class UsuarioController extends Controller{ /** * Mostrar listado de usuarios. */ public function index() { $usuarios = Usuario::paginate(15); return view('usuarios.index', ['usuarios' => $usuarios]); }
/** * Mostrar formulario de creación. */ public function create() { return view('usuarios.create'); }
/** * Almacenar un nuevo usuario. */ public function store(Request $request) { $validated = $request->validate([ 'nombre' => 'required|string|max:255', 'email' => 'required|email|unique:usuarios,email', 'password' => 'required|min:8|confirmed' ]);
$validated['password'] = Hash::make($validated['password']);
$usuario = Usuario::create($validated);
return redirect() ->route('usuarios.show', ['id' => $usuario->id]) ->with('mensaje', 'Usuario creado correctamente'); }
/** * Mostrar un usuario específico. */ public function show($id) { $usuario = Usuario::findOrFail($id); return view('usuarios.show', ['usuario' => $usuario]); }
/** * Mostrar formulario de edición. */ public function edit($id) { $usuario = Usuario::findOrFail($id); return view('usuarios.edit', ['usuario' => $usuario]); }
/** * Actualizar un usuario. */ public function update(Request $request, $id) { $usuario = Usuario::findOrFail($id);
$validated = $request->validate([ 'nombre' => 'required|string|max:255', 'email' => 'required|email|unique:usuarios,email,' . $id, 'password' => 'nullable|min:8|confirmed' ]);
if (isset($validated['password'])) { $validated['password'] = Hash::make($validated['password']); } else { unset($validated['password']); }
$usuario->update($validated);
return redirect() ->route('usuarios.show', ['id' => $usuario->id]) ->with('mensaje', 'Usuario actualizado correctamente'); }
/** * Eliminar un usuario. */ public function destroy($id) { $usuario = Usuario::findOrFail($id); $usuario->delete();
return redirect() ->route('usuarios.index') ->with('mensaje', 'Usuario eliminado correctamente'); }}Controladores resource (—resource)
Section titled “Controladores resource (—resource)”Los controladores resource son una forma eficiente de crear un controlador que contiene todos los métodos CRUD (Crear, Leer, Actualizar, Eliminar) necesarios para gestionar un recurso. Laravel proporciona una forma sencilla de generar estos controladores y sus rutas correspondientes.
Crear un controlador resource
Section titled “Crear un controlador resource”Para crear un controlador resource, utiliza la opción
--resourcemake:controllerphp artisan make:controller ProductoController --resourceEste comando generará un controlador con los siguientes métodos predefinidos:
- : Mostrar listado de recursosindex()
- : Mostrar formulario de creacióncreate()
- : Almacenar un nuevo recursostore()
- : Mostrar un recurso específicoshow()
- : Mostrar formulario de ediciónedit()
- : Actualizar un recursoupdate()
- : Eliminar un recursodestroy()
Registrar rutas para un controlador resource
Section titled “Registrar rutas para un controlador resource”Para registrar todas las rutas necesarias para un controlador resource, puedes utilizar el método
Route::resource()use AppHttpControllersProductoController;
Route::resource('productos', ProductoController::class);Este único comando creará automáticamente las siguientes rutas:
| Verbo HTTP | URI | Acción | Nombre de ruta |
|---|---|---|---|
| GET | /productos | index | productos.index |
| GET | /productos/create | create | productos.create |
| POST | /productos | store | productos.store |
| GET | /productos/{producto} | show | productos.show |
| GET | /productos/{producto}/edit | edit | productos.edit |
| PUT/PATCH | /productos/{producto} | update | productos.update |
| DELETE | /productos/{producto} | destroy | productos.destroy |
Personalizar rutas resource
Section titled “Personalizar rutas resource”Puedes personalizar las rutas resource de varias maneras:
Especificar solo ciertos métodos
Section titled “Especificar solo ciertos métodos”// Solo incluir estas accionesRoute::resource('productos', ProductoController::class)->only([ 'index', 'show']);
// Excluir estas accionesRoute::resource('productos', ProductoController::class)->except([ 'create', 'store', 'update', 'destroy']);Cambiar los parámetros de ruta
Section titled “Cambiar los parámetros de ruta”Por defecto, Laravel utiliza el nombre del recurso en singular como parámetro (por ejemplo, {producto}). Puedes cambiar esto con el método
parameters()Route::resource('productos', ProductoController::class) ->parameters(['productos' => 'producto_id']);Esto cambiará las rutas a /productos/{producto_id}.
Rutas resource anidadas
Section titled “Rutas resource anidadas”Puedes crear rutas resource anidadas para representar relaciones entre recursos:
Route::resource('categorias', CategoriaController::class);Route::resource('categorias.productos', CategoriaProductoController::class);Esto creará rutas como /categorias/{categoria}/productos/{producto}.
Controladores API resource
Section titled “Controladores API resource”Para APIs, a menudo no necesitas las rutas para mostrar formularios (
createeditphp artisan make:controller API/ProductoController --apiY para registrar solo las rutas API:
Route::apiResource('productos', APIProductoController::class);Esto registrará solo las rutas
indexstoreshowupdatedestroyPara registrar múltiples recursos API a la vez:
Route::apiResources([ 'productos' => APIProductoController::class, 'categorias' => APICategoriaController::class,]);Inyección de dependencias
Section titled “Inyección de dependencias”Laravel utiliza un contenedor de servicios que permite la inyección de dependencias en los controladores. Esto facilita el acceso a los servicios de la aplicación y mejora la testabilidad del código.
Inyección en el constructor
Section titled “Inyección en el constructor”Puedes inyectar dependencias en el constructor de tu controlador, y Laravel las resolverá automáticamente:
<?php
namespace AppHttpControllers;
use AppRepositoriesUserRepository;use AppServicesNotificationService;
class UsuarioController extends Controller{ protected $users; protected $notificationService;
public function __construct(UserRepository $users, NotificationService $notificationService) { $this->users = $users; $this->notificationService = $notificationService; }
public function show($id) { $usuario = $this->users->find($id); return view('usuarios.show', ['usuario' => $usuario]); }
public function notify($id) { $usuario = $this->users->find($id); $this->notificationService->sendWelcomeNotification($usuario);
return back()->with('mensaje', 'Notificación enviada'); }}Inyección en métodos
Section titled “Inyección en métodos”También puedes inyectar dependencias directamente en los métodos del controlador:
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;use AppServicesReporteService;
class ReporteController extends Controller{ public function generar(Request $request, ReporteService $reporteService, $tipo) { $datos = $reporteService->generarReporte($tipo, $request->input('desde'), $request->input('hasta'));
return view('reportes.mostrar', ['datos' => $datos, 'tipo' => $tipo]); }}En este ejemplo, Laravel inyectará automáticamente una instancia de
RequestReporteServiceInyección de modelos implícitos
Section titled “Inyección de modelos implícitos”Laravel permite la inyección implícita de modelos en las rutas y controladores. Esto significa que Laravel buscará automáticamente un modelo por su ID y lo inyectará:
use AppModelsUsuario;
Route::get('/usuarios/{usuario}', function (Usuario $usuario) { return $usuario;});
// En un controladorpublic function show(Usuario $usuario){ return view('usuarios.show', ['usuario' => $usuario]);}En estos ejemplos, Laravel buscará automáticamente un
Usuario{usuario}Personalizar la clave de resolución
Section titled “Personalizar la clave de resolución”Por defecto, la inyección implícita de modelos utiliza el campo
idgetRouteKeyName()<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Usuario extends Model{ /** * Obtener la clave utilizada por la inyección implícita de modelos. */ public function getRouteKeyName() { return 'nombre_usuario'; // En lugar de 'id' }}Inyección de servicios personalizados
Section titled “Inyección de servicios personalizados”Para que Laravel pueda inyectar tus servicios personalizados, debes registrarlos en el contenedor de servicios. Esto se hace típicamente en un proveedor de servicios (Service Provider):
<?php
namespace AppProviders;
use AppServicesReporteService;use AppServicesReporteServiceImpl;use IlluminateSupportServiceProvider;
class AppServiceProvider extends ServiceProvider{ public function register() { $this->app->bind(ReporteService::class, ReporteServiceImpl::class); }}Conclusión
Section titled “Conclusión”Los controladores en Laravel proporcionan una forma organizada y estructurada de manejar la lógica de tu aplicación. Utilizando controladores resource y la inyección de dependencias, puedes crear código limpio, mantenible y fácil de probar.
Recuerda que los controladores deben mantenerse “delgados” y enfocarse principalmente en recibir solicitudes HTTP y devolver respuestas. La lógica de negocio compleja debe delegarse a servicios o modelos para mantener una arquitectura limpia y escalable.