Rutas en CodeIgniter 4: Guía definitiva para configurar CRUD profesionales

- Andrés Cruz - EN In english

Video thumbnail

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:

  1. La URI (la URL que se desea mapear)
  2. El controlador que manejará la petición
  3. 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:

Ruta 404 post

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?
El namespace es 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 es Peliculas.php pero la clase se llama Pelicula, obtendrás un error 404 o 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:

Ruta correcta get

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

Ruta de tipo get y post

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:

Ruta get index

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:

PlaceholderDescripció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 registro

Este 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 routes

Este 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 /pelicula

Método: index()

Muestra el listado general de registros.

GET /pelicula/new

Mé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 HTTPRuta sugeridaFunciónPropósito
GETpeliculaindex()Listado de todas las películas.
GETpelicula/newnew()Muestra el formulario para crear una nueva película.
POSTpeliculacreate()Procesa y guarda la nueva película.
GETpelicula/edit/(:num)edit($id)Muestra el formulario para editar una película específica.
PUT / PATCHpelicula/(:num)update($id)Procesa la actualización de los datos.
DELETEpelicula/(: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 uses GET para 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:

  • index
  • create
  • new
  • edit
  • update
  • delete

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 routes

Este 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.

Aprende a configurar rutas en CodeIgniter 4 desde cero: métodos GET, POST, PUT y DELETE, grupos de rutas, placeholders, rutas con nombre y CRUD completo con ejemplos de código.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

Acepto recibir anuncios de interes sobre este Blog.