Saltar al contenido principal

¿Qué es un controlador?

En lugar de definir toda la lógica de manejo de solicitudes como closures dentro de los archivos de rutas, puedes organizar ese comportamiento usando clases “controladoras”. Los controladores permiten agrupar la lógica de manejo de solicitudes relacionadas en una única clase. Por ejemplo, la clase UserController puede manejar todas las solicitudes entrantes sobre usuarios: mostrar, crear, actualizar y eliminar. Por defecto, los controladores se guardan en el directorio app/Http/Controllers.

Crear un controlador

Para crear un nuevo controlador rápidamente, usa el comando Artisan make:controller. Todos los controladores de la aplicación se guardan por defecto en el directorio app/Http/Controllers.
php artisan make:controller UserController

Controlador básico

Una clase controladora puede tener varios métodos públicos que respondan a las solicitudes HTTP entrantes.
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Muestra el perfil del usuario indicado
     */
    public function show(string $id): View
    {
        return view('user.profile', [
            'user' => User::findOrFail($id)
        ]);
    }
}
Tras crear la clase y el método, puedes definir una ruta al método así:
use App\Http\Controllers\UserController;

Route::get('/user/{id}', [UserController::class, 'show']);
Cuando una solicitud entrante coincide con el URI de la ruta, se llama al método show de la clase App\Http\Controllers\UserController y se le pasan los parámetros de la ruta.
No es necesario que el controlador extienda una clase base. Sin embargo, puede ser útil extender una clase base cuando tienes métodos que deben compartir todos los controladores.

Controladores de una sola acción

Si la acción de un controlador es especialmente compleja, puede ser útil dedicar toda la clase a esa única acción. Para ello, define un único método __invoke dentro del controlador.
<?php

namespace App\Http\Controllers;

class ProvisionServer extends Controller
{
    /**
     * Provisiona un nuevo servidor web
     */
    public function __invoke()
    {
        // ...
    }
}
Al registrar la ruta de un controlador de una sola acción no hace falta indicar el método. Basta con pasar el nombre del controlador al router.
use App\Http\Controllers\ProvisionServer;

Route::post('/server', ProvisionServer::class);
Con la opción --invokable de make:controller puedes generar un controlador invocable.
php artisan make:controller ProvisionServer --invokable

Resource controllers

Si consideras cada modelo Eloquent de tu aplicación como un “recurso”, es habitual realizar el mismo conjunto de operaciones (CRUD) sobre cada uno. El enrutamiento de recursos de Laravel asigna las rutas típicas de creación/lectura/actualización/eliminación (CRUD) a un controlador con una sola línea de código. Con la opción --resource del comando make:controller puedes generar rápidamente un controlador que gestione esas acciones.
php artisan make:controller PhotoController --resource
Este comando genera un controlador en app/Http/Controllers/PhotoController.php. El controlador incluye stubs para cada una de las operaciones de recurso disponibles. A continuación, registra la ruta de recurso que apunta al controlador.
use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class);
Esta única declaración de ruta crea múltiples rutas para manejar las diversas acciones sobre el recurso. El controlador generado ya contiene stubs para cada una de esas acciones.
Método HTTPURIAcciónNombre de ruta
GET/photosindexphotos.index
GET/photos/createcreatephotos.create
POST/photosstorephotos.store
GET/photos/{photo}showphotos.show
GET/photos/{photo}/editeditphotos.edit
PUT/PATCH/photos/{photo}updatephotos.update
DELETE/photos/{photo}destroyphotos.destroy
Ejecutando php artisan route:list puedes ver rápidamente el resumen de las rutas de la aplicación.

Rutas de recurso parciales

Al declarar rutas de recurso puedes indicar un subconjunto de acciones que el controlador debe manejar.
use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class)->only([
    'index', 'show'
]);

Route::resource('photos', PhotoController::class)->except([
    'create', 'store', 'update', 'destroy'
]);

Rutas de recurso para API

Al declarar rutas de recurso para una API, es frecuente querer excluir rutas como create o edit, que muestran plantillas HTML. Con el método apiResource puedes excluir automáticamente esas dos rutas.
use App\Http\Controllers\PhotoController;

Route::apiResource('photos', PhotoController::class);

Inyección de dependencias

Inyección por constructor

El contenedor de servicios de Laravel se usa para resolver las dependencias de todos los controladores. Por eso puedes indicar mediante type-hint en el constructor las dependencias que necesita el controlador. Las dependencias declaradas se resuelven automáticamente y se inyectan en la instancia del controlador.
<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * Crea una nueva instancia del controlador
     */
    public function __construct(
        protected UserRepository $users,
    ) {}
}

Inyección por método

Además de la inyección por constructor, también puedes tipar dependencias en los métodos del controlador. Un caso habitual es inyectar una instancia de Illuminate\Http\Request en el método del controlador.
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Guarda un nuevo usuario
     */
    public function store(Request $request): RedirectResponse
    {
        $name = $request->name;

        // Procesamiento para guardar el usuario...

        return redirect('/users');
    }
}
Si el método del controlador también recibe entradas de parámetros de ruta, lista los argumentos de la ruta después de las otras dependencias. Por ejemplo, supongamos que se define la siguiente ruta:
use App\Http\Controllers\UserController;

Route::put('/user/{id}', [UserController::class, 'update']);
Puedes definir el método del controlador así, para tipar Illuminate\Http\Request y acceder también al parámetro id:
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Actualiza el usuario indicado
     */
    public function update(Request $request, string $id): RedirectResponse
    {
        // Actualización del usuario...

        return redirect('/users');
    }
}
Aprovechar la inyección de dependencias facilita sustituir por mocks en las pruebas y mejora la testabilidad del código.

Próximos pasos

Enrutamiento

Repasa cómo definir rutas y su relación con los controladores.
Última modificación el 13 de julio de 2026