Índice de contenido
- La importancia del Controlador
- Composición de las rutas
- Tipos de rutas
- Definición de rutas en app/Config/Routes.php
- Creación de un Controlador y el uso de Namespaces
- Agrupar rutas
- Parámetros en las rutas y URLs
- Placeholders
- Rutas con nombre
- Definir rutas para un CRUD completo
- Rutas comunes de CRUD
- Ver las rutas generadas
- Generar rutas de manera automática
- Organización recomendada del CRUD
- Método: index()
- Método: new()
- Método: create()
- Método: edit($id)
- Método: update($id)
- PUT vs PATCH
- Importante sobre seguridad
- Errores comunes al definir rutas
- Buenas prácticas en la nomenclatura de funciones
- ️ Tip Pro: Depuración de rutas
- ➡️ Redirecciones externas
- Conclusión
CodeIgniter 4, como framework moderno que es, cuenta con un completo sistema para manejar las rutas, algo que ya lleva tiempo presente en otros frameworks como Laravel o Django. En estos, existe una capa adicional de ruteo que actúa como intermediario entre las URLs del sistema y los controladores, permitiéndonos definir con precisión qué función del controlador va a procesar cada URL.
En la entrada anterior vimos cómo eliminar registros en CodeIgniter 4, donde trabajamos con los controladores y sus funciones, creamos nuestro primer controlador y definimos una ruta de tipo GET.
La importancia del Controlador
Recuerda que CodeIgniter 4 es un framework MVC (Modelo-Vista-Controlador), y cada capa tiene una responsabilidad bien definida:
- Vista: La capa que ve el usuario final; se encarga de la presentación.
- Modelo: Se encarga de manipular los datos y realizar el CRUD con la base de datos.
- Controlador: Es el intermediario; comunica la vista con el modelo y gestiona la lógica de negocio.
- Rutas: En CodeIgniter 4, las rutas son obligatorias (cuando el auto-enrutado está desactivado) y definen cómo accedemos a los recursos del controlador desde una URL.
Composición de las rutas
Al igual que ocurre en la mayoría de los frameworks que implementan una capa de ruteo, una ruta básica requiere tres parámetros esenciales:
- La URI (la URL que se desea mapear)
- El controlador que manejará la petición
- La función dentro del controlador que ejecutará el proceso
Además de estos tres parámetros, debemos definir el tipo de ruta (o método HTTP), el cual analizamos más en detalle a continuación. Por ejemplo, la siguiente es una ruta de tipo POST:
$routes->post('/save_form', 'Admin::save');Tipos de rutas
En CodeIgniter 4 disponemos de múltiples tipos de rutas según el método HTTP que necesitemos. Si definimos una ruta de tipo GET, únicamente resolverá peticiones de ese tipo. De forma similar, si queremos procesar datos enviados desde un formulario, necesitamos una ruta POST. Elegir el método correcto no es solo una buena práctica: también es una medida de seguridad, pues evita que una URL acepte peticiones que no debería.
Definición de rutas en app/Config/Routes.php
Las rutas se definen en el archivo app/Config/Routes.php. Antes de empezar, asegúrate de establecer $routes->setAutoRoute(false); si quieres definir tus rutas manualmente y tener control total sobre ellas. De esta forma, solo serán accesibles las rutas que tú declares explícitamente.
$routes->post('/save_form', 'Admin::save');Por lo tanto, si intentamos acceder a esta ruta de tipo POST mediante una petición desde el navegador (que por defecto es GET), obtendremos el siguiente error:

Un simple 404, porque estamos accediendo mediante una petición GET a un método que únicamente está configurado para ser consumido vía POST.
La solución es sencilla: definir una ruta adicional de tipo GET para esa misma URI:
$routes->get('/', 'Pelicula::index');
$routes->get('/save_form', 'Admin::save');
$routes->post('/save_form', 'Admin::save');Creación de un Controlador y el uso de Namespaces
Para que una ruta funcione, necesitamos un controlador que la respalde. Crearemos uno llamado Pelicula.php en la carpeta app/Controllers:
<?php
namespace App\Controllers;
class Pelicula extends BaseController {
public function index() {
return "Hola Mundo";
}
}Y añadimos una función save() para manejar el guardado:
public function save() { return "save"; }¿Qué es el Namespace?
Elnamespacees un mecanismo para agrupar clases bajo una ruta lógica que coincide con la estructura de carpetas del proyecto. Es fundamental para que el framework pueda autocargar la clase correctamente. Siempre debe seguir la estructura:App\Controllers. Si el nombre del archivo esPeliculas.phppero la clase se llamaPelicula, obtendrás un error404o un error de carga de clase. El archivo y la clase deben tener exactamente el mismo nombre.
Con todo correctamente configurado, tendremos el resultado esperado:

La ruta anterior funciona para ser consumida tanto por GET como por POST, ya que definimos ambas apuntando al mismo controlador y función.
Por supuesto, también contamos con los métodos PUT, PATCH y DELETE:
$routes->get('products', 'Product::feature');
$routes->post('products', 'Product::feature');
$routes->put('products/(:num)', 'Product::feature');
$routes->patch('products/(:num)', 'Product::feature');
$routes->delete('products/(:num)', 'Product::feature');Cada uno de estos métodos responde a un tipo de operación diferente, y emplearlos correctamente es la base para construir una API o CRUD semánticamente correcto.
Agrupar rutas
Cuando varias rutas comparten un segmento común en la URI —por ejemplo, el prefijo admin—, CodeIgniter 4 nos permite agruparlas con el método $routes->group() para evitar repetir ese segmento en cada definición:
$routes->group('admin', function ($routes) {
$routes->get('save_form', 'Admin::save');
$routes->post('save_form', 'Admin::save');
});Con esto, la URI completa para acceder a esas rutas pasa a ser:
http://testcodeigniter4.test/admin/save_form

Además, puedes anidar grupos para crear estructuras más profundas, sin límite de niveles:
$routes->group('admin', function ($routes) {
$routes->group('user', function ($routes) {
$routes->get('save_form', 'Admin::save');
$routes->post('save_form', 'Admin::save');
});
});La URI resultante sería:
http://testcodeigniter4.test/admin/user/save_form
Y si necesitas agregar más rutas dentro del mismo grupo, simplemente las declaras al mismo nivel:
$routes->group('admin', function ($routes) {
$routes->group('user', function ($routes) {
$routes->get('save_form', 'Admin::save');
$routes->post('save_form', 'Admin::save');
$routes->get('index', 'Admin::index');
});
});Quedando accesible en:
http://testcodeigniter4.test/admin/user/index
Con la siguiente función en el controlador:
public function index() { return "Admin"; }Tendremos el resultado esperado:

Parámetros en las rutas y URLs
También podemos definir parámetros dentro de las rutas para pasar datos dinámicos directamente desde la URL. Por ejemplo, para recibir un número identificador:
$routes->get('save_form/(:num)', 'Admin::save/$1', ['as' => 'admin_save']);El parámetro capturado ($1) se pasa automáticamente como argumento a la función del controlador:
public function save($id) { return "save: " . $id; }Placeholders
Los placeholders nos permiten restringir o validar el tipo de dato que se espera en un segmento de la URL. CodeIgniter 4 ofrece los siguientes de forma nativa:
| Placeholder | Descripción |
|---|---|
(:any) | Hace match con cualquier carácter que se pase por la URL, incluyendo /. |
(:segment) | Igual que (:any), pero excluye el carácter /. |
(:num) | Hace match únicamente con números enteros. |
(:alpha) | Hace match con cualquier carácter del alfabeto (sin números ni símbolos). |
(:alphanum) | Hace match con cualquier combinación de letras y números. |
(:hash) | Similar a (:segment), pero codifica el valor internamente. Útil para IDs ofuscados. |
Rutas con nombre
Podemos asignar un nombre a cualquier ruta mediante la opción 'as'. Esto nos permite referenciarla por su nombre en lugar de escribir la URI directamente. La ventaja es clara: si en algún momento necesitas cambiar la URI, solo lo haces en la definición de la ruta y el resto del código se actualiza automáticamente:
$routes->get('save_form', 'Admin::save', ['as' => 'admin_save']);Desde una vista, usamos la función helper route_to() para generar la URL a partir del nombre:
<?= route_to('admin_save') ?>Si la ruta recibe argumentos, los pasamos como parámetros adicionales:
<?= route_to('admin_save', $movie->id) ?>Definir rutas para un CRUD completo
Lo más habitual en cualquier aplicación es necesitar operaciones CRUD: crear, leer, actualizar y eliminar recursos. Para implementarlo de forma manual, necesitarías al menos 7 rutas distintas: una para el listado, una para mostrar el formulario de creación, otra para procesar ese formulario, otra para el formulario de edición, otra para procesarla, una para eliminar, y opcionalmente una para mostrar el detalle. Por suerte, CodeIgniter 4 nos ofrece el método $routes->resource(), que genera todas esas rutas con una sola línea:
$routes->resource('photos', $options);Puedes consultar en detalle las rutas que genera en la documentación oficial.
Rutas comunes de CRUD
En CodeIgniter 4, las rutas más utilizadas para cualquier operación CRUD son las siguientes:
$routes->get('pelicula', 'Pelicula::index'); // Listado de elementos
$routes->get('pelicula/new', 'Pelicula::new'); // Formulario de creación
$routes->post('pelicula', 'Pelicula::create'); // Procesa y guarda el nuevo registro
$routes->get('pelicula/(:num)/edit', 'Pelicula::edit'); // Formulario de edición
$routes->put('pelicula/(:num)', 'Pelicula::update'); // Procesa la actualización
$routes->delete('pelicula/(:num)', 'Pelicula::delete'); // Elimina el registroEste esquema representa las URIs y métodos HTTP usados por convención para realizar las operaciones CRUD a nivel de aplicación web.
Ver las rutas generadas
Para inspeccionar en cualquier momento qué rutas tiene registradas tu aplicación, CodeIgniter 4 incluye el comando de spark:
php spark routesEste comando imprime en consola una tabla con el método HTTP, la URI y el handler asociado. Si una ruta no aparece en esa tabla, no existe para el framework.
Generar rutas de manera automática
Una característica interesante de CodeIgniter 4 es la posibilidad de generar rutas automáticamente a partir de los métodos públicos que tenga registrados tu controlador. Para habilitarlo, debes activar la opción en tu archivo de rutas:
$routes->setAutoRoute(true);Dado el siguiente controlador de ejemplo:
<?php
namespace App\Controllers;
class Pelicula extends BaseController {
public function index()
{
echo "Hola Mundo";
}
public function test($x = 0, $n = 10)
{
echo "Hola Mundo test " . $x . " " . $n;
}
// public function new()
// {
// echo view("pelicula/create");
// }
// public function create()
// {
// echo "Procesando el Form!";
// }
public function edit($id)
{
echo view("pelicula/edit");
}
public function update($id)
{
echo "Procesando el Form! " . $id;
}
}Al remover las rutas definidas manualmente y ejecutar php spark routes, verás que el framework habrá generado automáticamente lo siguiente:
+--------+-----------------------+------------------------------------------+
| Method | Route | Handler |
+--------+-----------------------+------------------------------------------+
| auto | / | \App\Controllers\Home::index |
| auto | home | \App\Controllers\Home::index |
| auto | home/index[/...] | \App\Controllers\Home::index |
| auto | pelicula | \App\Controllers\Pelicula::index |
| auto | pelicula/index[/...] | \App\Controllers\Pelicula::index |
| auto | pelicula/test[/...] | \App\Controllers\Pelicula::test |
| auto | pelicula/edit[/...] | \App\Controllers\Pelicula::edit |
| auto | pelicula/update[/...] | \App\Controllers\Pelicula::update |
+--------+-----------------------+------------------------------------------+Es una opción particularmente útil en proyectos pequeños o en fases tempranas de desarrollo, donde la velocidad importa más que el control exhaustivo de las rutas. Sin embargo, para aplicaciones en producción se recomienda definir las rutas manualmente para mayor seguridad y claridad.
Organización recomendada del CRUD
La estructura más utilizada por convención en CodeIgniter 4 para un CRUD completo sería la siguiente:
GET /peliculaMétodo: index()
Muestra el listado general de registros.
GET /pelicula/newMétodo: new()
Muestra el formulario para crear un nuevo recurso.
POST /pelicula
Método: create()
Procesa el formulario y guarda el nuevo registro en la base de datos.
GET /pelicula/edit/{id}Método: edit($id)
Muestra el formulario de edición precargado con los datos del registro correspondiente.
PUT /pelicula/{id}Método: update($id)
Procesa el formulario y actualiza el registro existente.
DELETE /pelicula/{id}Método: delete($id) o destroy($id) — Elimina el registro de la base de datos.
PUT vs PATCH
PUT→ Reemplaza toda la entidad con los datos enviados.PATCH→ Actualiza parcialmente la entidad; solo los campos enviados.
Ejemplo práctico:
- Si el usuario edita un post completo →
PUT - Si solo cambia el título →
PATCH
Resumen de las rutas y métodos del CRUD:
| Método HTTP | Ruta sugerida | Función | Propósito |
|---|---|---|---|
GET | pelicula | index() | Listado de todas las películas. |
GET | pelicula/new | new() | Muestra el formulario para crear una nueva película. |
POST | pelicula | create() | Procesa y guarda la nueva película. |
GET | pelicula/edit/(:num) | edit($id) | Muestra el formulario para editar una película específica. |
PUT / PATCH | pelicula/(:num) | update($id) | Procesa la actualización de los datos. |
DELETE | pelicula/(:num) | delete($id) | Elimina el recurso de la base de datos. |
Importante sobre seguridad
Los datos enviados se comportan de forma muy diferente según el método HTTP utilizado:
GET→ Los datos viajan en la URL y son visibles en la barra del navegador, el historial y los logs del servidor. Nunca usesGETpara enviar información sensible.POST→ Los datos van encapsulados en el cuerpo de la petición, lo que los hace más seguros para el envío de formularios con información sensible.
Errores comunes al definir rutas
Uno de los errores más frecuentes al comenzar con CodeIgniter 4 es la discrepancia entre el nombre del archivo del controlador y el nombre de la clase:
- Archivo:
Pelicula.php - Clase definida como:
class Peliculas
Esta diferencia genera un error de carga de clase y devuelve un 404. El nombre del archivo y el nombre de la clase deben coincidir exactamente, respetando mayúsculas y minúsculas.
Buenas prácticas en la nomenclatura de funciones
Aunque técnicamente puedes dar cualquier nombre a las funciones de tu controlador, seguir las convenciones establecidas es una práctica indispensable en proyectos colaborativos. Los nombres estándar son:
indexcreateneweditupdatedelete
Seguir estas convenciones permite que cualquier desarrollador entienda de un vistazo qué hace cada función, sin necesidad de leer el código ni hacer debugging.
️ Tip Pro: Depuración de rutas
Si alguna vez tu ruta no responde como esperas, no adivines. Ejecuta siempre el siguiente comando desde la raíz de tu proyecto para verificar qué rutas reconoce el framework:
php spark routesEste comando imprime una tabla clara con el método HTTP, la URI, el manejador (handler) y cualquier restricción aplicada. Si tu ruta no aparece en esa tabla, no existe para CodeIgniter 4.
➡️ Redirecciones externas
A veces es necesario redirigir una ruta hacia una URL externa. Puedes hacerlo fácilmente dentro de app/Config/Routes.php usando el método addRedirect():
$routes->addRedirect('google', 'https://google.com');Esto es extremadamente útil para manejar URLs obsoletas, hacer migraciones de rutas sin romper enlaces existentes, o delegar procesos a servicios de terceros sin salir de la estructura de rutas de tu aplicación.
Conclusión
Esta es una organización muy sólida y probada para trabajar con rutas en CodeIgniter 4. Puede variar según las necesidades de cada proyecto, pero es el esquema más utilizado hoy en día y el que más se sigue por convención en la comunidad.
Lo importante es:
- Entender qué hace cada tipo de petición HTTP y cuándo usarlo.
- Ser consistente con los nombres de funciones y URIs.
- No reinventar la rueda; las convenciones existen por una razón.
- Mantener claridad en la estructura para facilitar el mantenimiento del proyecto.
Con esto ya tienes un dominio sólido del sistema de rutas de CodeIgniter 4. El siguiente paso es aprender a crear una API REST en CodeIgniter 4.