Capítulo 2.5: Rutas API
Tiempo de estudio: 45 minutos
1. ¿Qué es una ruta? Explicación sencilla
Imagina que tu controlador (PlanetController
) es un gran centro de oficinas, y cada uno de sus métodos (index
, store
, show
) es un departamento separado que realiza su trabajo.
Una Ruta (Route) es una placa de dirección en la entrada del edificio. Dice:
- "Si alguien llegó a la dirección
/planets
con el método GET — envíelo al departamentoindex
(mostrar todo)". - "Si alguien llegó a la dirección
/planets
con el método POST con un paquete (datos) — envíelo al departamentostore
(crear uno nuevo)".
Sin rutas, ninguna solicitud del mundo exterior encontrará el departamento que necesita en tu código. El archivo principal para estas "placas de dirección" en la API es routes/api.php
.
En Laravel 11+, por defecto no hay una "libreta de direcciones API". La creamos nosotros mismos ejecutando el comando php artisan install:api
. Ahora tenemos el archivo routes/api.php
, que es el centro de control principal para todas las rutas de nuestra API.
Diferencia clave entre api.php
y web.php
:
- Prefijo
/api
: Laravel añade automáticamente/api
a todas las URLs de este archivo. La ruta/planets
se convierte en/api/planets
. - "Sin estado" (Stateless): Aquí no hay sesiones ni cookies, como en la web normal. Cada solicitud es independiente y debe contener toda la información para la autenticación (normalmente, un token de API en los encabezados).
2. El camino del novato: Creación manual de una ruta
Vamos a crear una única ruta manualmente para entender el principio. Nuestro objetivo es hacer que la URL /api/planets
muestre una lista de todos los planetas.
Abre routes/api.php
y escribe:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlanetController; // Indicamos dónde está nuestro controlador
// (1) (2) (3)
Route::get( '/planets', [PlanetController::class, 'index'] );
// ^ ^ ^
// (Método HTTP) (URL) (Qué controlador y método llamar)
Analicemos esta línea por partes:
Route::get(...)
— decimos: "Esta ruta solo funciona para solicitudes GET".'/planets'
— es la URL que Laravel escuchará. Con el prefijo/api
, la dirección completa seráhttp://space-api.test/api/planets
.[PlanetController::class, 'index']
— es el "punto de destino". Decimos: "Cuando llegue la solicitud, encuentra la clasePlanetController
y llama a su métodoindex()
".
¡Ahora todo está conectado! Solicitud -> Ruta -> Controlador -> Método.
¿Y si necesitamos obtener un planeta por su ID? Por ejemplo, /api/planets/5
.
// Ruta para obtener un planeta específico
Route::get('/planets/{planet}', [PlanetController::class, 'show']);
Aquí {planet}
es una "plantilla" o variable. Laravel entiende que en este lugar puede haber cualquier cosa (ID, slug). Luego, pasa este valor al método show(Planet $planet)
. Esta "magia", cuando Laravel encuentra el planeta por ID automáticamente, se llama Route Model Binding.
3. El camino del maestro: apiResource
— una línea para gobernarlos a todos
Crear cada ruta manualmente (para index
, show
, store
, update
, destroy
) es tedioso. Los desarrolladores de Laravel lo entienden, por eso crearon un asistente potente — apiResource
.
Elimina todo lo que escribimos y reemplázalo con una sola línea:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlanetController;
Route::apiResource('planets', PlanetController::class);
¿Qué hace esta sola línea bajo el capó? Crea automáticamente un conjunto completo de rutas para las operaciones CRUD estándar que ya implementamos en el controlador.
Método | URL | Se dirige al método | Propósito |
---|---|---|---|
GET | /api/planets |
index() |
Obtener una lista de todos los planetas |
POST | /api/planets |
store() |
Crear un nuevo planeta |
GET | /api/planets/{planet} |
show() |
Mostrar un planeta específico |
PUT/PATCH | /api/planets/{planet} |
update() |
Actualizar un planeta existente |
DELETE | /api/planets/{planet} |
destroy() |
Eliminar un planeta |
Puedes Verificarlo tú mismo. Ejecuta el siguiente comando en la terminal:
Verás una tabla con todas las rutas creadas. apiResource
es tu mejor amigo para ahorrar tiempo al crear APIs estándar.
4. Misiones especiales y orden de las rutas
¿Qué pasa si necesitamos una ruta no estándar, que no está en apiResource
? Por ejemplo, obtener un planeta aleatorio en la dirección /api/planets/random
.
Vamos a añadirla. Pero aquí hay una trampa mortal en la que caen 9 de cada 10 novatos.
Orden incorrecto (¡NO FUNCIONA!):
Route::apiResource('planets', PlanetController::class);
Route::get('/planets/random', [PlanetController::class, 'random']); // <-- NO FUNCIONARÁ
Route::apiResource
, que creó la ruta GET /planets/{planet}
. Cuando solicites /planets/random
, Laravel pensará que "random" es el ID de un planeta e intentará encontrar en la base de datos un planeta con el ID "random", y obtendrás un error.
Orden correcto (¡FUNCIONA!):
<?php
use App\Http\Controllers\PlanetController;
use Illuminate\Support\Facades\Route;
// 1. Primero declaramos las rutas ESPECÍFICAS
Route::get('/planets/random', [PlanetController::class, 'random']);
// 2. Y solo después declaramos las rutas GENERALES con variables
Route::apiResource('planets', PlanetController::class);
⚠️ ¡Importante!
Para probar la ruta
api/planets/random
, debes añadir un nuevo manejador enPlanetController
:
Regla: Declara siempre las rutas más específicas (como /random
) antes de las rutas más generales y con plantillas (como /{planet}
).
5. Agrupación: Poniendo orden
Cuando hay muchas rutas, se pueden y se deben agrupar.
A. Versionado de la API
Para no romper las aplicaciones antiguas que usan tu API en el futuro, es costumbre añadir una versión en la URL, por ejemplo /api/v1/...
.
<?php
Route::prefix('v1')->group(function () {
// Todas las rutas dentro de este grupo obtendrán el prefijo /v1
// URL final: /api/v1/planets
Route::get('/planets/random', [PlanetController::class, 'random']);
Route::apiResource('planets', PlanetController::class);
});
B. Protección de rutas (Middleware) Imagina que cualquiera puede ver los planetas, pero solo los usuarios autorizados pueden crearlos, actualizarlos y eliminarlos.
<?php
// Rutas públicas, accesibles para todos
Route::get('/planets', [PlanetController::class, 'index']);
Route::get('/planets/{planet}', [PlanetController::class, 'show']);
// Grupo de rutas que requieren un "pase" (autenticación)
Route::middleware('auth:sanctum')->group(function () {
Route::post('/planets', [PlanetController::class, 'store']);
Route::put('/planets/{planet}', [PlanetController::class, 'update']);
Route::delete('/planets/{planet}', [PlanetController::class, 'destroy']);
});
Aquí middleware('auth:sanctum')
es como un guardia de seguridad que comprueba el "pase" de cualquiera que intente acceder a las rutas dentro del grupo.
6. Pruebas con Postman
Ahora que todas las rutas están establecidas, es hora de probarlas.
- Si usas Herd: Tu sitio ya está funcionando en una dirección como
http://space-api.test
. - Si no: Inicia el servidor local con el comando
php artisan serve
. La dirección seráhttp://localhost:8000
.
Abre Postman y envía las solicitudes:
GET http://space-api.test/api/planets
GET http://space-api.test/api/planets/random
POST http://space-api.test/api/planets
(no olvides añadir el cuerpo de la solicitud JSON en la pestañaBody
->raw
->JSON
).
Ejemplo de solicitud POST:
{
"name": "Kepler-186f",
"description": "Primera planeta de tamaño terrestre en la zona habitable",
"size_km": 15000,
"solar_system": "Kepler-186",
"is_habitable": true
}
8. Errores comunes de enrutamiento
- 404 Not Found
- URL incorrecta (
/api/planet
en lugar de/api/planets
) - Olvidaste
php artisan serve
- URL incorrecta (
- 405 Method Not Allowed
- Método HTTP incorrecto (por ejemplo, GET en lugar de POST)
- Missing Controller
- Error tipográfico en el nombre del controlador (
PlanetControler
)
- Error tipográfico en el nombre del controlador (
- Route Name Collision
- Nombres de ruta duplicados
Cuestionario de refuerzo
🚀 Resumen del capítulo:
¡Has construido las "rutas hiperespaciales" para la API espacial! Ahora:
- 🗺️ Todos los endpoints están disponibles en
/api/...
- 🔗 Las rutas de recursos están conectadas al controlador
- 🛡️ Se han añadido rutas personalizadas para operaciones especiales
- ✅ Las rutas se han probado con Postman
¡El universo está abierto a solicitudes! A continuación, añadiremos protección contra la "basura espacial": la validación de datos.
📌 Verificación:
- Ejecuta
php artisan route:list
- Asegúrate de ver 5+ rutas para planets
- Verifica el funcionamiento de GET /api/planets en el navegador/Postman
⚠️ Si error 404:
- Verifica la presencia de
Route::apiResource
enroutes/api.php
- Asegúrate de que el servidor esté en ejecución (
php artisan serve
)- Para Windows: permite el puerto 8000 en el firewall