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

Video thumbnail

CodeIgniter 4, como framework moderno que es, ha desarrollado un completo sistema para manejar las rutas, algo que ya lleva tiempo en otros framework como lo son Laravel o Django, en el cual tenemos una capa o nivel adicional para manejar las rutas, por lo tanto, tenemos un mecanismo para indicar que función del controlador va a procesar que URL mediante las rutas.

Ya en la anterior entrada vimos como eliminar registros en CodeIgniter 4 y trabajamos con los controladores y las funciones, además de que creamos nuestro primer controlador y función asociada y una ruta de tipo get.

La importancia del Controlador

Recuerda que CodeIgniter es un framework MVC (Modelo-Vista-Controlador):

  • Vista: La capa que ve el usuario final.
  • 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 son obligatorias y definen cómo accedemos a los recursos del controlador.

Composición de las rutas

Al igual que ocurre en la mayoría de los frameworks que trabajan con la capa de ruteo, básicamente definen 3 parámetros básicos:

  1. La URI
  2. El controlador
  3. La función dentro del controlador, que es la que se va a encargar de hacer el proceso

Además del tipo de ruta que lo hablamos un poco más abajo que para este ejemplo es de tipo post:

$routes->post('/save_form', 'Admin::save');

Tipo de rutas

En Codeigniter 4, tenemos múltiples tipos de rutas que podemos emplear según el método a emplear, es decir, si empleamos rutas de tipo get, significa un solamente van a poder resolver las peticiones de tipo, get, ahora si nos interesa enviar un post, que generalmente lo empleamos para por ejemplo, guardar datos desde un formulario, tenemos que crear una ruta de tipo post:

Definición de Rutas en Config/Routes.php

Las rutas se definen en el archivo app/Config/Routes.php. Antes de empezar, asegúrate de tener comentada la línea de $routes->setAutoRoute(false); si quieres definir tus rutas manualmente y tener total control sobre ellas.

$routes->post('/save_form', 'Admin::save');

Por lo tanto, si intentamos acceder a esta ruta de tipo post mediante una consulta desde el navegador, nos va a dar el siguiente error:

Ruta 404 post

Simplemente un 404 porque estamos accediendo mediante una petición de tipo get a un método que solamente está configurado para ser accedido vía post.

Así que, tenemos que definir otra ruta como get, o simplemente agregamos otra ruta para el get:

$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. 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 con esto, para la siguiente función:

public function save(){ return "save"; }

¿Qué es el Namespace?
El Namespace es un mecanismo para agrupar clases en carpetas. Es fundamental para que el framework pueda importar la clase automáticamente. Siempre debe seguir la estructura de carpetas: App\Controllers. Si cambias esta ruta o el nombre de la clase (por ejemplo, si el archivo se llama Peliculas pero la clase Pelicula), obtendrás un error 404 o un error de carga.

Tenemos el resultado esperado:

Ruta correcta get

Porque la ruta anterior funciona para ser consumida tanto por get como por post.

Por supuesto, tenemos también para los de tipo put, patch o 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');

Que las podemos emplear dependiendo del tipo de operación que queramos realizar.

Agrupar rutas

En caso de que tengamos varias rutas con parte de la misma URI igual; por ejemplo supongamos un ahora diremos que nuestra ruta de tenga la palabra admin en la misma:

$routes->group('admin', function ($routes) {    
   $routes->get('save_form', 'Admin::save');    
   $routes->post('save_form', 'Admin::save'); 
});

Ahora tenemos que agregar un admin al path; en mi caso:

http://testcodeigniter4.test/admin/save_form 

Ruta de tipo get y post

Puedes agregar tantos niveles de agrupación como quieras o necesites:

$routes->group('admin', function ($routes) {    
  $routes->group('user', function ($routes) {        
     $routes->get('save_form', 'Admin::save');        
     $routes->post('save_form', 'Admin::save');    
   });
});

Y para accederla:

http://testcodeigniter4.test/admin/user/save_form

Y queremos crear otra ruta:

$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');    }); 
});

Perfectamente podemos hacerlo:

http://testcodeigniter4.test/admin/user/index

Y con la siguiente función en nuestro controlador:

public function index()    {        return "Admin";    }

Tenemos lo siguiente:

Ruta get index

Parámetros paras las rutas y ulrs

También podemos definir parámetros a las rutas para pasar datos adicionales; por ejemplo un número:

$routes->get('save_form/(:num)', 'Admin::save/$1', ['as' => 'admin_save']);

Desde la función:

public function save($id)    {        return "save: ".$id;    }

Placeholders

Podemos configurar distintos placeholders según el tipo de dato que queremos recibir:

PlaceholdersDescripción
(:any)Hará match con cualquier carácter que le pasemos por la URL.
(:segment)Igual que el anterior excluyendo el /.
(:num)Match con cualquier entero.
(:alpha)Match con cualquier carácter del alfabeto.
(:alphanum)Match con cualquier carácter del alfabeto o número.
(:hash) 

Rutas con nombre

Nosotros también podemos darle un nombre a nuestra ruta, más adelante, en otra entrada veremos un ejemplo práctico de todo esto, pero suponte que simplemente es una referencia que nosotros le damos para poder referencias a la ruta mediante el nombre y NO directamente colocar la URI; la ventaja de esto se explica por sí sola y de esta manera nosotros podemos variar perfectamente la URI sin necesidad de actualizar la referencia en nuestro código:

$routes->get('save_form', 'Admin::save', ['as' => 'admin_save']);

Y desde una vista; simplemente colocamos la referencia al nombre:

<?= route_to('admin_save') ?>

Si recibiera argumentos:

<?= route_to('admin_save', $movie->id) ?>

Definir nuestras rutas para una operación tipo CRUD

Lo más usual en los sistemas es que necesitemos realizar operaciones tipo CRUD, es decir, para crear, leer, actualizar y eliminar alguna entidad, como puedes ver, por ejemplo para la vista de crear y actualizar necesitamos definir dos rutas post cada una de estas operaciones, una para mostrar el formulario y otra para procesar la información más la vista para el listado serian un total de 7 rutas diferentes para hacer una operación genérica como hacer un CRUD; por suerte framework modernos como lo son CodeIgniter 4, contamos con un método que nos permite definir mediante una sola función o método todos los tipos de rutas que necesitemos:

$routes->resource('photos', $options);

Puedes ver las rutas que les tenemos que especificar en la documentación oficial.

Rutas comunes

En C4, podemos decir que las rutas comunes a utilizar en cualquier aplicación son:

$routes->get('pelicula','Pelicula::index'); // De tipo get para generar un listado de elementos
$routes->get('pelicula/new','Pelicula::new'); // De tipo get para pintar el formulario de creación
$routes->post('pelicula','Pelicula::create');// De tipo create para procesar el formulario al momento de crear un recurso
$routes->get('pelicula/xx/edit','Pelicula::edit');// De tipo get para pintar el formulario para editar un elemento
$routes->put('pelicula/xx','Pelicula::update');// de tipo put para procesar todo el formulario de un registro existente
$routes->delete('pelicula/xx','Pelicula::delete'); // de tipo delete que como sorpresa, permite eliminar un registro

El anterior esquema son las URIs usadas por excelencia para realizar cada una de las operaciones señaladas y los tipos de rutas comunes para realizar los famosos CRUD a nivel de la aplicación.

Ver las rutas generadas

Para poder ver las rutas generadas a nivel de la aplicación, tenemos el comando de spark:

php spark routes

Generar rutas de manera automática

Una característica muy interesante que tiene CodeIgniter, es la de poder generar rutas de manera automática, segun los métodos que tengamos registrados, para esto, en nuestro archivo de rutas, tenemos que habilitarlo:

$routes->setAutoRoute(true);

Dado el siguiente controlador:

<?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;
    }
}

Y remueves las rutas anteriormente definidas y revisas que rutas han sido generadas:

+--------+-----------------------+------------------------------------------+
| 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 cuando tienes una aplicación en la cual puedas aprovechar este tipo de característica.

Organización recomendada del CRUD

Una organización común sería:

GET /pelicula

Método: index()

Mostrar formulario crear

GET /pelicula/new

Método: new()

Crear recurso

POST /pelicula

Método: create()

Mostrar formulario editar

GET /pelicula/edit/{id}

Método: edit($id)

Actualizar

PUT /pelicula/{id}

Método: update($id)

Eliminar

DELETE /pelicula/{id}

Método: delete($id) o destroy($id)

PUT vs PATCH

  • PUT → Actualiza toda la entidad.
  • PATCH → Actualiza parcialmente la entidad.

Ejemplo:

  • Si editas todo el post → PUT
  • Si solo cambias el título → PATCH

Resumen:

Método HTTPRuta SugeridaFunciónPropósito
GETpeliculaindexListado de todas las películas.
GETpelicula/newnewMuestra el formulario para crear una nueva película.
POSTpeliculacreateProcesa y guarda la nueva película.
GETpelicula/edit/(:num)editMuestra el formulario para editar una película específica.
PUT/PATCHpelicula/(:num)updateProcesa la actualización de los datos.
DELETEpelicula/(:num)deleteElimina el recurso de la base de datos.

Importante sobre seguridad

Los datos enviados por:

  • GET → Viajan en la URL.
  • POST → Van encapsulados en la petición.

Errores comunes

Uno muy común:

  • Archivo se llama Pelicula.php
  • Clase se llama Peliculas

Eso genera error.

Los nombres deben coincidir exactamente.

Por eso POST es más seguro para enviar formularios.

Buena práctica de nombres

Aunque puedes inventar nombres, no es recomendable.

Usar convenciones como:

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

Permite que cualquier desarrollador entienda rápidamente lo que hace la aplicación sin tener que hacer debugging.

️ Tip Pro: Depuración de Rutas

Si alguna vez tu ruta no responde como esperas, no adivines. Utiliza siempre la terminal en la raíz de tu proyecto para verificar qué rutas reconoce el framework:

php spark routes

Esto te mostrará una tabla clara con el método, el URI, el manejador (handler) y cualquier restricción aplicada. Si tu ruta no aparece ahí, no existe para CodeIgniter.

➡️ Redirecciones externas

A veces, es necesario redirigir una ruta a una URL externa. Puedes hacerlo fácilmente en tu archivo Config/Routes.php:

$routes->addRedirect('google', 'https://google.com');

Esto es extremadamente útil para manejar enlaces obsoletos o delegar procesos a servicios de terceros sin salir de la estructura de tus rutas.

Conclusión

Esta es una organización muy buena para trabajar con rutas en CodeIgniter 4.

Puede cambiar, sí.
Pero este es el esquema más utilizado hoy en día y el que más se sigue por convención.

Lo importante es:

  • Entender qué hace cada tipo de petición.
  • Ser consistente con los nombres.
  • No reinventar la rueda.
  • Mantener claridad en la estructura.

Con esto ya tienes un reforzamiento sólido del uso de rutas.

El siguiente paso consiste en aprender a crear una Rest API en CodeIgniter 4.

¿Problemas con tus rutas en CodeIgniter 4? Aprende a configurar métodos GET, POST, PUT, DELETE, grupos de rutas y recursos para un desarrollo escalable.

Acepto recibir anuncios de interes sobre este Blog.

Andrés Cruz

EN In english