PHPackages                             dlunire/dlroute - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dlunire/dlroute

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

dlunire/dlroute
===============

Sistema avanzado de enrutamiento HTTP impulsado por autómatas finitos. Altamente eficiente, flexible y de alto rendimiento. Úsalo como motor central de DLUnire o intégralo fácilmente en cualquier proyecto PHP.

v2.0.3(2w ago)2296↓50%1AGPL-3.0-or-laterPHP

Since Apr 8Pushed 2w agoCompare

[ Source](https://github.com/dlunire/dlroute)[ Packagist](https://packagist.org/packages/dlunire/dlroute)[ GitHub Sponsors](https://github.com/dlunire)[ RSS](/packages/dlunire-dlroute/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (7)Versions (18)Used By (1)

DLRoute
=======

[](#dlroute)

✨ Sponsors
----------

[](#-sponsors)

Gracias a las siguientes personas y empresas por apoyar el desarrollo de **DLRoute** y la futura **v2.0.0** (autómatas puros).

### Patrocinadores Activos

[](#patrocinadores-activos)

---

**¿Quieres formar parte de esto?**

[❤️ Patrocíname en GitHub Sponsors](https://github.com/sponsors/dlunire)

---

DLRoute no es "otro enrutador PHP más". Es un pipeline de enrutamiento construido sobre la teoría de lenguajes formales —los mismos fundamentos utilizados en los compiladores— aplicada por primera vez al despacho de peticiones HTTP en PHP.

```
composer require dlunire/dlroute
```

Requiere **PHP 8.2+**. Funciona con cualquier proyecto PHP —con o sin framework—.

---

Por qué DLRoute es diferente
----------------------------

[](#por-qué-dlroute-es-diferente)

Cualquier otro enrutador de PHP —FastRoute, Symfony Routing, Laravel Router— fue construido en torno a un único objetivo: mapear URLs a controladores lo más rápido posible. El emparejamiento (*matching*) era el problema; todo lo demás era secundario.

DLRoute se diseñó bajo una premisa distinta: **el enrutamiento es un pipeline de procesamiento formal, no una tabla de búsqueda.**

Esa premisa produce una arquitectura que no existe en ningún otro enrutador de PHP.

---

Lo que ningún otro enrutador de PHP hace
----------------------------------------

[](#lo-que-ningún-otro-enrutador-de-php-hace)

### 1. Parser de querystring mediante autómata finito

[](#1-parser-de-querystring-mediante-autómata-finito)

Todos los demás enrutadores utilizan `parse_str()`, una función que existe desde PHP 4.

DLRoute la reemplaza con un autómata finito que procesa la cadena de consulta **byte por byte en una sola pasada**, con estados explícitos (`QUERY_NAME` → `QUERY_VALUE`), emitiendo DTOs tipados e mutables con el desplazamiento exacto en bytes (*offset*) de cada token en la cadena original.

```
// GET /?campo=valor&activo
$params = (new QueryParamComposer())->get_query_params();

$params['campo']->value;         // "valor"
$params['campo']->offset;        // 0   — posición en bytes del nombre
$params['campo']->offset_value;  // 6   — posición en bytes del valor
$params['campo']->length;        // 5

$params['activo']->value;        // null — parámetro sin valor
```

Ningún otro enrutador de PHP expone metadatos de posición a nivel de byte para los parámetros de la querystring.

---

### 2. Lexer de sintaxis de rutas con diagnóstico de posición exacta

[](#2-lexer-de-sintaxis-de-rutas-con-diagnóstico-de-posición-exacta)

Cuando defines una ruta con una sintaxis inválida, DLRoute no lanza una excepción genérica. El `RouterLexer` analiza la definición de la ruta **carácter por carácter** y emite un diagnóstico completamente accionable:

```
// Ruta inválida
DLRoute::get('/{ciencia?=algo}/users', fn() => []);
```

```
RouteException: Expected closing brace (}) after «?» (position 9).
Received instead: «?=algo}/users».
Optional parameters must follow the format → «{param?}»
Route defined: «/{ciencia?=algo}/users»

```

Compara esto con lo que hace Laravel ante un método HTTP inválido:

**Laravel** → Una página silenciosa `404 HTML`

**DLRoute** → JSON estructurado con el error exacto, archivo, línea y traza de la pila (*stack trace*)

Esa es la diferencia entre un sistema con contratos formales y uno sin ellos.

---

### 3. Telemetría como ciudadano de primera clase en el núcleo

[](#3-telemetría-como-ciudadano-de-primera-clase-en-el-núcleo)

`TelemetryRequest` reside en `DLRoute\Core\Telemetry` —no es un middleware, no es un plugin—. Fue diseñado desde el inicio como parte del motor.

```
DLRoute::get('/{resource?}', function() {
    return TelemetryRequest::telemetry("Mi API");
});
```

```
{
    "message":     "Mi API",
    "route":       "/api/users",
    "uri":         "/api/users?filter=active",
    "base_url":    "[https://mi-dominio.com](https://mi-dominio.com)",
    "domain":      "mi-dominio.com",
    "is_https":    true,
    "port":        443,
    "local_port":  80,
    "timestamp":   "2026-06-18T01:20:47+00:00",
    "cliente_ip":  "203.0.113.1",
    "method":      "GET",
    "proxy":       true,
    "query_param": {
        "filter": {
            "name":         "filter",
            "offset":       0,
            "value":        "active",
            "offset_value": 7,
            "length":       6
        }
    }
}
```

Una sola llamada. Cero configuración. Funciona correctamente detrás de Cloudflare, proxies inversos de Nginx y túneles, diferenciando automáticamente el `port` (de cara al cliente) del `local_port` (puerto interno del servidor).

Para lograr un resultado equivalente en Laravel necesitas: Telescope + configuración de proxies de confianza + un paquete de logging externo.

---

### 4. Contratos tipados en el registro de rutas

[](#4-contratos-tipados-en-el-registro-de-rutas)

`Methods::GET` es un enum, no una cadena de texto. El enrutador valida el tipo **antes de registrar la ruta**. Si pasas algo inválido, falla inmediatamente con un error JSON estructurado.

```
// ❌ Incorrecto
DLRoute::match(['david'], new RouteHandler(...));

// ✅ Correcto
DLRoute::match([Methods::GET, Methods::POST], new RouteHandler(...));
```

```
{
    "status": false,
    "error": "DLRoute::match: Expected «DLRoute\\Enums\\Methods». Received «david» instead.",
    "details": { "filename": "...", "line": 200 }
}
```

Laravel responde silenciosamente con un `404 HTML` ante la misma entrada.

---

### 5. Detección de subdirectorios sin configuración

[](#5-detección-de-subdirectorios-sin-configuración)

DLRoute calcula la ruta real de la petición mediante **aritmética de posición de bytes** —sin `str_replace()`, sin expresiones regulares—:

```
OFFSET = LENGTH(dir) - 1
route  = substr(uri, OFFSET)

```

Determinista y O(1), independientemente de si el nombre del subdirectorio aparece repetido en la URI.

```
{
    "route":    "/api/products",
    "uri":      "/subdir/subdir/api/products",
    "dir":      "/subdir/subdir",
    "base_url": "[https://example.com/subdir/subdir](https://example.com/subdir/subdir)"
}
```

---

Comparativa de características
------------------------------

[](#comparativa-de-características)

CapacidadDLRouteFastRouteSymfony RouterLaravel RouterParser de querystring por autómata finito✅❌❌❌Metadatos de posición de token a nivel de byte✅❌❌❌Lexer de sintaxis de rutas con diagnósticos✅❌❌❌Posición exacta en bytes en errores de sintaxis✅❌❌❌Telemetría nativa en el núcleo✅❌❌❌Errores JSON estructurados✅❌❌❌Contratos de métodos HTTP tipados (enum)✅❌❌❌Detección de subdirectorios sin configuración✅❌❌❌Respuesta JSON automática desde un array✅❌❌❌Parámetros opcionales de forma nativa✅❌❌solución alternativaTipo MIME explícito por ruta✅❌❌❌Cero dependencias externas✅✅❌❌---

Inicio rápido
-------------

[](#inicio-rápido)

### 1. Estructura del proyecto

[](#1-estructura-del-proyecto)

```
mi-proyecto/
├── public/
│   └── index.php
├── app/
│   └── Controllers/
│       └── ApiController.php
└── vendor/

```

### 2. Punto de entrada

[](#2-punto-de-entrada)

```
