Enrutamiento - Routing

El enrutamiento, también conocido como routing en inglés, es un proceso fundamental en el desarrollo web que consiste en asignar URLs a diferentes acciones en una aplicación web. En un sistema de enrutamiento típico, cada URL representa una ruta específica dentro de la aplicación y está asociada a un controlador o función encargada de manejar esa ruta.

El enrutamiento permite que una aplicación web responda de manera adecuada a las solicitudes de los usuarios, dirigiéndolos a la página correcta según la URL que han solicitado. Además, el enrutamiento también puede utilizarse para aplicar lógica adicional, como la autenticación de usuarios o la validación de datos, antes de mostrar el contenido solicitado.

Ejemplo básico de enrutamiento:

                
                    
use Lib\Router\Route;
 
Route::get('/', function () {
  return 'Hello World';
});

Rutas con controladores

Las rutas con controladores permiten definir de manera clara y organizada las acciones que se deben realizar al recibir una solicitud HTTP en una ruta específica. Esto promueve un diseño más estructurado y mantenible para la aplicación. Por ejemplo, se pueden definir rutas con controladores de dos formas:

1. Utilizando clases de controladores

Las rutas definidas con clases de controlador consisten en un arreglo que contiene el nombre de la clase de controlador WelcomeController y el nombre del método index.

                
                    
use App\Http\Controllers\WelcomeController;
use Lib\Router\Route;
 
Route::get('/', [WelcomeController::class, 'welcome']);

En este caso, la ruta "/" se asociará al método index de la clase WelcomeController en la clase HomeController en el archivo WelcomeController.

2. Utilizando el formato string

Estas rutas están compuestas por el nombre de la clase de controlador WelcomeController, un caracter @ y el nombre del método index.

                
                    
use Lib\Router\Route;
 
Route::get('/', 'WelcomeController@welcome');

Ambas formas logran el mismo resultado, pero el uso de clases de controlador proporciona una estructura más clara y orientada a objetos para la definición de rutas.

Rutas de API

Las rutas de API son URLs que representan una ruta de controlador o función en una aplicación web. Estas URLs se utilizan para interactuar con la aplicación web desde el cliente. Por defecto, las rutas de API se definen en el archivo routes/api.php, pero estas rutas están deshabilitadas por defecto.

Para habilitar las rutas de API, sigue estos pasos:

  1. Dirígete al directorio app/.
  2. Localiza el archivo Kernel.php. Este archivo es el encargado de iniciar la aplicación.
  3. Abre el archivo Kernel.php y encuentra el método register().
  4. Descomenta la línea BaseKernel::$additionalRoutes dentro del método register().

El archivo Kernel.php tiene la siguiente estructura:

                
                    
namespace App;
 
use Lib\Kernel\BaseKernel;
use Lib\Kernel\Contracts\KernelInterface;
 
class Kernel implements KernelInterface
{
 /**
 * Bootstraps the application.
 */
 public static function boot()
 {
    BaseKernel::boot();
 }
 
 /**
 * Registers the routes for the application.
 */
 public static function register()
 {
    BaseKernel::$additionalRoutes = [
        // sprintf('%s/api.php', routes_path()),
    ];
 
    BaseKernel::register();
 }
}

Una vez habilitadas las rutas API desde el Kernel, ya puedes definir las rutas de API en el archivo routes/api.php.

Inyección de dependencias

La inyección de dependencias es un concepto importante en JMFramework que permite pasar automáticamente las dependencias necesarias a través de los métodos o constructores de las clases. En el contexto de las rutas, JMFramework puede inyectar automáticamente las dependencias requeridas en la función de ruta.

Un ejemplo básico de inyección de dependencias en una ruta sería:

                
                    
Route::get('/example', function (Request $request) {
  //
});

En este ejemplo, JMFramework inyecta automáticamente una instancia de Lib\Http\Request en la función de ruta. Esto permite acceder a los datos de la solicitud HTTP, como los parámetros de la URL, las cabeceras y el cuerpo de la solicitud. La inyección de dependencias es una técnica poderosa que facilita la escritura de código limpio y mantenible en la aplicación.

Protección CSRF

Para proteger tu aplicación contra ataques CSRF, asegúrate de incluir un token CSRF en todos los formularios que envíen peticiones POST, PUT, PATCH o DELETE.

Puedes agregar el token CSRF a tus formularios de la siguiente manera en Twig:

                
                    
<form method="POST" action="/login">
 {{ csrf() }}
 ...
</form>

La función csrf() generará automáticamente un campo de entrada oculto con el token CSRF necesario para proteger tu formulario. Este token se enviará junto con tu formulario y se utilizará para verificar la autenticidad de la solicitud.

Al incluir el token CSRF en tus formularios, puedes proteger tu aplicación contra ataques CSRF y garantizar la seguridad de tus usuarios.

Parámetros de ruta

Los parámetros de ruta permiten definir partes variables en una URL, lo que facilita la creación de rutas dinámicas en tu aplicación. Por ejemplo, en la ruta /books/:id, ":id" es un parámetro de ruta que puede tener diferentes valores según la solicitud.

                
                    
Route::get('/books/:id', [BookController::class, 'show']);

Ejemplo de uso del parametro en el controlador BookController en el metodo show:

                
                    
public function show(int $id)
{
  return 'book ' . $id;
}

Puede definir tantos parámetros de ruta como requiera su ruta:

                
                    
Route::get('/books/:id/:name/:author', [BookController::class, 'show']);

Al utilizar parámetros de ruta, puedes crear rutas más flexibles y dinámicas en tu aplicación.

Nombres de ruta

Los nombres de ruta te permiten asignar un nombre único a una ruta en tu aplicación, lo que facilita referenciarla enlaces y redirecciones. Esto es especialmente útil cuando necesitas cambiar la URL de una ruta, ya que solo necesitas actualizar el nombre de la ruta en lugar de todos los lugares donde se utiliza esa ruta.

En tu archivo de definición de rutas, puedes asignar un nombre a una ruta de la siguiente manera:

                
                    
Route::get('/', [WelcomeController::class, 'welcome'])
  ->name('welcome.index');

Una vez que has asignado un nombre a una ruta, puedes generar URL para esa ruta utilizando el helper route() en Twig de la siguiente manera:

                
                    
<a href="{{ route('welcome.index') }}">Enlace</a>

Al utilizar nombres de ruta, puedes hacer que tu código sea más legible y mantenible al tiempo que facilitas la actualización de las URL en tu aplicación.

Prefijos de ruta

Los prefijos de ruta te permiten agrupar un conjunto de rutas bajo un mismo prefijo, lo que facilita la organización y el mantenimiento de tu aplicación. Esto es útil cuando deseas aplicar middleware, como la autenticación, a un grupo de rutas relacionadas.

Por ejemplo, puedes definir un prefijo de ruta "/api" para todas las rutas de tu API de la siguiente manera:

                
                    
Route::setPrefix('/api');
 
Route::middleware([ApiAuthMiddleware::class])->group(function () {
  Route::get(
    '/user',
    fn () =>
    response()->json([
        'data' => auth()->user('api'),
    ])->send()
  );
});

En este ejemplo, todas las rutas dentro del grupo tendrán el prefijo "/api", lo que significa que la ruta para listar usuarios sería "/api/user". Además, el nombre de la ruta se puede utilizar para generar URLs utilizando el helper route() en Twig.

Al utilizar prefijos de ruta, puedes organizar tu aplicación de manera más eficiente y facilitar la aplicación de middleware y otras configuraciones a grupos específicos de rutas.

Agrupando rutas por controladores

Cuando se agrupan rutas por controladores, es importante tener en cuenta que solo se debe especificar el nombre del controlador, no la ruta completa. Por ejemplo, si el controlador se llama WelcomeController, solo se debe usar 'WelcomeController' y no WelcomeController::class. Esto se debe a que al agrupar rutas por controladores, JMFramework asume automáticamente que las rutas deben dirigirse al controlador especificado.

Ejemplo básico de agrupamiento de rutas por controladores:

                
                    
Route::controller('WelcomeController')->group(function () {
    Route::get('/', 'index')->name('welcome.index');
    Route::get('/about', 'about')->name('welcome.about');
    Route::get('/contact', 'contact')->name('welcome.contact');
});

En este ejemplo, todas las rutas dentro del grupo WelcomeController están asociadas al controlador especificado sin necesidad de usar ::class. Al agrupar rutas de esta manera, se logra una organización más clara y mantenible del código.

Agrupando rutas por middlewares

Al agrupar rutas por middlewares, es posible utilizar ::class después del nombre del middleware. Esto permite una forma más sencilla de especificar los middlewares que se aplicarán a un grupo de rutas.

Ejemplo de agrupación de rutas por middleware:

                
                    
Route::middleware([Middleware::class])->group(function () {
    Route::get('/', fn () => 'Página principal');
    Route::get('/about', fn () => 'Página de información');
    Route::get('/contact', fn () => 'Página de contacto');
});

En este ejemplo, todas las rutas dentro del grupo están envueltas por el middleware especificado. Esto es útil para aplicar ciertas funcionalidades o restricciones a un conjunto específico de rutas. Al agrupar rutas por middlewares de esta manera, se logra una organización más clara y mantenible del código.

Agregar nuevos archivos de rutas

Si deseas agregar una nueva ruta o archivo de ruta, debes seguir los siguientes pasos:

  • Crear un nuevo archivo de ruta en el directorio routes/ por ejemplo routes/admin.php.
  • Registrar el nuevo archivo de ruta en el archivo Kernel.php, en el método register(), dentro de BaseKernel::$additionalRoutes.
  • Una vez registrada el nuevo archivo de ruta debes definir el prefijo de la ruta como se muestra en prefijos de ruta.