PHPackages                             rguezque/katya-router - 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. [Framework](/categories/framework)
4. /
5. rguezque/katya-router

ActiveRouter[Framework](/categories/framework)

rguezque/katya-router
=====================

A lightweight PHP router.

v2.0.0(5mo ago)119711MITPHPPHP &gt;=8.2.12

Since Sep 29Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/rguezque/katya-router)[ Packagist](https://packagist.org/packages/rguezque/katya-router)[ Docs](https://www.github.com/rguezque/katya-router)[ RSS](/packages/rguezque-katya-router/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (8)DependenciesVersions (10)Used By (1)

Katya
=====

[](#katya)

A lightweight PHP router

**Tabla de contenidos**

- [Install](#install)
- [Configuration](%22configuration%22)

    - [Autoloader](#autoloader)
- [Routing](#routing)

    - [Shortcuts](#shortcuts)
    - [Controllers](#controllers)
- [Routes group](#routes-group)
- [Wildcards](#wildcards)
- [Views](#views)
- [Request](#request)
- [Response](#response)

    - [HttpHeaders](#httpheaders)
    - [Stream](#stream)
- [SapiEmitter](#sapiemitter)
- [Session](#session)
- [Services](#services)
- [Variables](#variables)
- [DB Connection](#db-connection)

    - [Connecting using an URL](#connecting-using-an-url)
    - [Auto connect](#auto-connect)
    - [Create new instances](#create-new-instances)
    - [SQLite connection](#sqlite-connection)
- [Middleware](#middleware)
- [CORS](#cors)
- [Environment Management](#environment-management)
- [helpers\*](#helpers)

Install
-------

[](#install)

Desde la terminal en la raíz del proyecto:

```
composer require rguezque/katya-router
```

Configuration
-------------

[](#configuration)

Para servidor **Apache**, en el directorio del proyecto crea y edita un archivo `.htaccess` con lo siguiente:

```

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

```

Para **Nginx** edita el archivo de configuración de la siguiente forma:

```
server {
    location / {
        try_files $uri $uri/ /index.php;
    }
}

```

Para prueba desde el servidor *inbuilt* de PHP, dentro del directorio del proyecto ejecuta en la terminal:

```
php -S localhost:80
```

Y abre en el navegador web la dirección `http://localhost:80`

### Autoloader

[](#autoloader)

Desde la terminal, ubícate dentro del directorio del proyecto y ejecuta:

```
composer dump-autoload -o
```

Routing
-------

[](#routing)

```
require __DIR__.'/vendor/autoload.php';

use rguezque\{
    HttpStatus,
    Katya,
    Request,
    Response
};
use rguezque\Exceptions\{
    RouteNotFoundException,
    UnsupportedRequestMethodException
};

$router = new Katya;

$router->route(Katya::GET, '/', function(Request $request) {
    return new Response('hola mundo!');
});

try {
    $router->run(Request::fromGlobals());
} catch(RouteNotFoundException $e) {
    $message = sprintf('Not Found%s', $e->getMessage());
    (new Response($message, HttpStatus::HTTP_NOT_FOUND))->send();
} catch(UnsupportedRequestMethodException $e) {
    $message = sprintf('Not Allowed%s', $e->getMessage());
    (new Response($message, HttpStatus::HTTP_METHOD_NOT_ALLOWED))->send();
}
```

Cada ruta se define con el método `Katya::route`, que recibe 3 argumentos, el método de petición (solo son soportados `GET`, `POST`, `PUT`, `PATCH` y `DELETE`), la ruta y el controlador a ejecutar para dicha ruta. Los controladores siempre reciben un objeto `Request` que contiene los métodos necesarios para manejar una petición (Ver [Request](#request)) y deben devolver un `Response` (Ver [Response](#response)).

Para iniciar el router se invoca el método `Katya::run` y se le envía un objeto `Request`.

Si el router se aloja en un subdirectorio, este se puede especificar en el *array* de opciones al crear la instancia del router. Así mismo, se puede definir el directorio default donde se buscarán los archivos al renderizar una plantilla.

```
$katya = new Katya('/nombre_directorio_base');
```

Tip

El router devuelve tres posibles excepciones; `RouteNotFoundException` cuando no se encuentra una ruta, `UnsupportedRequestMethodException` cuando un método de petición no está soportado por el router o un `UnexpectedValueException` cuando el controlador no devuelve un tipo `Response`. Utiliza un `try-catch` para atraparlas y manejar el `Response` apropiado como se ve en el ejemplo.

### Shortcuts

[](#shortcuts)

Los atajos `Katya::get`, `Katya::post`, `Katya::put`, `Katya::patch` y `Katya::delete` sirven respectivamente para agregar rutas de tipo `GET`, `POST`, `PUT`, `PATCH` y `DELETE` al router.

```
$katya = new Katya;
$katya->get('/', function(Request $request) {
    return new Response('Hello')
});

$katya->post('/', function(Request $request) {
    $data = [
        'name' => 'John',
        'lastname' => 'Doe'
    ];

    return new JsonResponse($data);
});
```

Note

Para detener el router en cualquier momento puedes utilizar `Katya::halt` que recibe un objeto `Response` que se envía antes de detener los procesos del router.

### Controllers

[](#controllers)

Los controladores pueden ser: una función anónima, un método estático o un método de un objeto.

```
// Usando una función anónima
$katya->get('/user', function(Request $request) {
    //...
});

// Usando un método estático
$katya->get('/user', ['App\Controller\GreetingController', 'showProfileAction']);
// o bien
use App\Controller\UserController;
$katya->get('/user', [UserController::class, 'showProfileAction']);
$katya->get('/user/permissions', [UserController::class, 'showPermissionsAction']);

// Usando un método de un objeto
$user = new App\Controller\UserController();
$katya->get('/user', [$user, 'showProfileAction']);
```

Tip

Si se usan métodos de un objeto como controladores se recomienda nombrar las clases con el sufijo `Controller` y los métodos con el sufijo `Action` para identificarlos mejor a través del proyecto.

Routes group
------------

[](#routes-group)

Para crear grupos de rutas bajo un mismo prefijo se utiliza `Katya::group`; recibe 2 argumentos, el prefijo de ruta y una función anónima que recibe un objeto `Group` con el cual se definen las rutas del grupo.

```
// Se generan las rutas "/foo/bar" y "/foo/baz"
$katya->group('/foo', function(Group $group) {
    $group->get('/bar', function(Request $request) {
        return new Response(' Hello foobar');
    });

    $group->get('/baz', function(Request $request, Services $service) {
        // Registrado previamente como un servicio
        $template = $services->view->fetch('welcome')
        return new HtmlResponse($template);
    });
});
```

Wildcards
---------

[](#wildcards)

Los *wildcards* son parámetros definidos en la ruta. El router busca las coincidencias de acuerdo a la petición y los envía como argumentos al controlador de ruta a través del objeto `Request`, estos argumentos son recuperados con el método `Request::getParams` que devuelve por default un objeto `Parameters` donde cada clave se corresponde con el mismo nombre de los *wildcards*. El argumento por default de esté método es `Request::PARAMS_ASSOC` el cual indica que el *array* de parámetros tiene índices nombrados correspondientes a los *wildcards* y no numéricos.

Los *wildcards* permiten la definición de `regex` opcionales para hacer más estrictas las rutas.

```
// Si `edad` no es un número entero, arrojará una excepción `RouteNotFoundException`
$katya->get('/hola/{nombre}/{edad: \d+}', function(Request $request) {
    $params = $request->getParams(); // Devuelve un objeto Parameter
    return new JsonResponse(['nombre' => $params['nombre'], 'edad' => $params['edad']]);
});
```

El objeto `Parameters` tiene los siguientes métodos:

- `get(string $key, mixed $default = null)`: Devuelve un parámetro por nombre o el valor default especificado, si no existe.
- `set(string $key, mixed $value)`: Agrega o sobrescribe un parámetro.
- `all()`: Devuelve todo el array de parámetros.
- `has(string $key)`: Devuelve `true` si un parámetro existe, `false` en caso contrario.
- `valid(string $key)`: Devuelve `true` si un parámetro existe y si no es `null` y no está vacío; `false` en caso de que no cumpla alguna de las condiciones anteriores.
- `remove(string $key)`: Elimina un parámetro por nombre.
- `clear()`: Elimina todos los parámetros.
- `keys()`: Devuelve un array lineal con los nombres de todos los parámetros.
- `gettype(string $key)`: Devuelve el tipo de dato de un parámetro.

Si los *wildcards* fueron definidos como expresiones regulares puras, envía el argumento `Request::PARAMS_NUM` el cual devuelve un *array* lineal con los valores de las coincidencias encontradas.

```
$katya->get('/hola/(\w+)/(\w+)/(\d+)', function(Request $request) {
    $params = $request->getParams(Request::PARAMS_NUM); // Devuelve un array lineal
    list($nombre, $apellido, $edad) = $params;
    return new Response(sprintf('Hola %s %s, tu edad recibida es: %d', $nombre, $apellido, $edad));
});
```

Important

Evita mezclar parámetros nombrados y expresiones regulares en la misma definición de una ruta, pues no podrás recuperar por nombre los que hayan sido definidos como *regex*. En todo caso si esto sucede, envía el argumento `Request::PARAMS_BOTH` para recuperar un ***array*** con todos los parámetros en el orden que hayan sido definidos en la ruta.

Views
-----

[](#views)

Las vistas son el medio por el cual el router devuelve y renderiza un objeto `HtmlResponse` con contenido HTML en el navegador. La única configuración que se necesita es definir el directorio donde estarán alojadas las plantillas en la instancia de la clase `ViewEngine`.

```
use rguezque\View;

// Standalone
$view = new ViewEngine(
    __DIR__.'/templates' // Directorio donde se alojan los templates
);

// Enviandolo como un servicio
$services = new Services();
$services->register('view', function() {
    return new ViewEngine(__DIR__.'/templates');
});
$router->setServices($services);
```

El método `ViewEngine::fetch` recibe el nombre de la plantilla (puede omitirse la terminación del archivo) y opcionalmente un array con variables. Devuelve en un string lo contenidos de la plantilla, listo para ser enviado como un `HtmlResponse`. Los archivos deben nombrarse con la terminación `.view.php`.

```
$router->get(Request $request, Services $service): Response {
    $view = $service->view();
    $data = [
    	'home': '/',
    	'about': '/about-us',
    	'contact': '/contact-us'
	];
	$template = $view->fetch('menu', $data);
    return new HtmlResponse($template);
}
```

Recibe los parámetros enviados en `$data` (según el ejemplo del bloque de código de arriba)

```
//menu.php

```

Otros métodos para agregar argumentos a la plantilla antes de invocar `fetch`, son:

- `addArgument(string $key, mixed $value)`: Agrega un argumento por nombre a la vez.
- `addArguments(array $data)`: Agrega un array asociativo de argumentos de tipo clave-valor a los ya existentes.
- `setArguments(array $data)`: Asigna o sobrescribe los argumentos para la plantilla.

Request
-------

[](#request)

Los métodos de la clase `Request` que empiezan con `get` devuelven un objeto `Parameters` con excepción de `Request::getParams` que puede variar.

- `fromGlobals()`: Crea un objeto `Request` con las variables globales PHP.
- `getQuery()`: Devuelve el array de parámetros `$_GET`.
- `getBody()`: Devuelve el array de parámetros `$_POST`.
- `getPhpInputStream(int $option = Request::RAW_DATA)`: Devuelve el *stream* `php://input` sin procesar. Si se recibe la petición en formato JSON se envía un argumento `Request::JSON_DECODE`; si es un *query string* se envía el argumento`Request::PARSED_STR`. En estos últimos dos casos, devolverá un objeto `Parameters`.
- `getServer()`: Devuelve el array de parámetros `$_SERVER`.
- `getCookies()`: Devuelve el array de parámetros `$_COOKIE`.
- `getFiles()`: Devuelve el array de parámetros `$_FILES`.
- `getParams(Request::PARAMS_ASSOC)`: Devuelve el array de parámetros nombrados de una ruta solicitada. Dependiendo de la definición de los *wildcards* de una ruta, se puede especificar el formato de datos a devolver (Ver [Wildcards](#wildcards)).
- `getAllHeaders()`: Devuelve todos los encabezados HTTP recibidos en la actual petición.
- `setQuery(array $query)`: Asigna valores a `$_GET`.
- `setBody(array $body)`: Asigna valores a `$_POST`.
- `setServer(array $server)`: Asigna valores a `$_SERVER`.
- `setCookies(array $cookies)`: Asigna valores a `$_COOKIE`.
- `setFiles(array $files)`: Asigna valores a `$_FILES`.
- `setParams(array $params)`: Asigna valores al array de parámetros nombrados.
- `buildQuery(string $uri, array $params)`: Genera y devuelve una cadena de petición `GET` en una URI.

Response
--------

[](#response)

Métodos de la clase `Response`.

- `clear()`: Limpia los valores del `Response`.
- `setStatusCode(int $code)`: Asigna un código númerico de estatus HTTP.
- `getStatusCode()`: Devuelve el actual código de estatus HTTP.
- `headers`: Atributo público de tipo `HttpHeaders`. Contiene métodos para agregar encabezados HTTP al `Response`.
- `body`: Atributo público de tipo `Stream`. Contiene métodos para agregar contenido al cuerpo del `Response`.

Tip

Utiliza `JsonResponse` para devolver datos de una API en formato `JSON` y `HtmlResponse` para devolver contenido `html`.

### HttpHeaders

[](#httpheaders)

- `set(string $key, string $value)`: Agrega un encabezado.
- `get(string $key, ?string $default = null)`: Devuelve un encabezado por nombre.
- `remove(string $key)`: Elimina un encabezado por nombre.
- `clear()`: Elimina todos los encabezados.
- `all()`: Devuelve todos los encabezados en un *array*.
- `has(string $key)`: Devuelve `true` si un encabezado existe, `false` en caso contrario.

### Stream

[](#stream)

- `write(mixed $string)`: Escribe contenido y retorna el total de bytes escritos; o `false` en error.
- `read(int $length)`: Lee el *stream*.
- `getContents()`: Recupera el contenido restante del *stream* desde la posición actual del puntero.
- `detach()`: Libera y devuelve el flujo actual.
- `getSize()`: Devuelve el tamaño en bytes del *stream*.
- `tell()`: Devuelve la posición actual del puntero de lectura/escritura del *stream*.
- `eof()`: Devuelve `true` si el puntero del *stream* está al final del archivo; `false` en caso contrario.
- `seek(int $offset, int $whence = SEEK_SET)`: Establece el indicador de posición del archivo referenciado por el *stream*. La nueva posición, medida en bytes desde el principio del archivo, se obtiene sumando el desplazamiento a la posición especificada por consiguiente.
- `rewind()`: Rebobina el puntero del *stream* al inicio.
- `close()`: Cierra el flujo contra escritura.

SapiEmitter
-----------

[](#sapiemitter)

Emite el `Response` con el método estático `SapiEmitter::emit`.

```
$response = $router->run(Request::fromGlobals());
SapiEmitter::emit($response);
```

Para más control utiliza `try-catch`:

```
try {
    $response = $app->run(Request::fromGlobals());
} catch(UnexpectedValueException $e) {
    $response = new Response('el controlador retorno un resultado no válido', HttpStatus::HTTP_EXPECTATION_FAILED);
} catch(UnsupportedRequestMethodException $e) {
    $response = new Response('Método de petición no permitido', HttpStatus::HTTP_METHOD_NOT_ALLOWED);
} catch(RouteNotFoundException $e) {
    $response = new Response('Ruta no encontrada', HttpStatus::HTTP_NOT_FOUND);
}

SapiEmitter::emit($response);
```

Session
-------

[](#session)

La clase `Session` sirve para la creación de sesiones y la administración de variables de `$_SESSION` que son almacenadas en un *namespace* privado del router. Se inicializa o selecciona una colección de variables de sesión con el método estático `Session::create` el cual devuelve un **singleton** de la clase. Los métodos disponibles son:

- `create(string $session_name = Session::NAMESPACE)`: Crea o reanuda una sesión. Se envía como argumento un nombre para la sesión; aunque no es obligatorio es recomendable hacerlo para evitar colisiones de variables con otras aplicaciones. Por default se asigna un nombre definido por el router. > \[!TIP\] Utiliza variables de entorno (`.env`) para declarar un nombre de sesión a través de toda la aplicación.
- `start()`: Inicia o retoma la sesión activa.
- `started()`: Devuelve `true` si la sesión está activa.
- `set(string $key, mixed $value)`: Crea o sobrescribe una variable de sesion.
- `get(string $key, mixed $default = null)`: Devuelve una variable de sesión, si no existe devuelve el valor default que se asigne en el segundo parámetro.
- `all()`: Devuelve un array con todas las variables de sesión del actual *namespace*.
- `has(string $key)`: Devuelve `true` si existe una variable de sesión.
- `valid(string $key)`: Devuelve `true` si una variable de sesión no es `null` y no está vacía.
- `remove(string $key)`: Elimina una variable de sesión.
- `clear()`: Elimina todas las variables de sesión.
- `destroy()`; Destruye la sesión actual junto con las cookies y variables de sesión.

```
$session = Session::create();
$session->set('nombre', 'Juan');
$session->set('edad', 30);
$session->get('nombre);
```

Note

`Session::start` se invoca automáticamente en cada llamado del resto de métodos pero se deja como acceso público.

Services
--------

[](#services)

La clase `Services` sirve para registrar servicios que se utilizarán en todo el proyecto. Con el método `Services::register` agregamos un servicio, este recibe 2 parámetros, un nombre y una función anónima. Para quitar un servicio `Services::unregister` recibe el nombre del servicio (o servicios, separados por coma) a eliminar.

Para asignarlos al router se envía el objeto `Services` a través del método `Katya::setServices`, a partir de aquí, cada controlador recibirá como tercer argumento la instancia de `Services`. Un servicio es invocado como si fuera un método más de la clase o bien como si fuera un atributo en contexto de objeto.

Opcionalmente se puede seleccionar que servicios específicamente serán utilizados en determinada ruta o grupo de rutas con `Route::useServices` el cual recibe los nombres de los servicios registrados previamente, separados por comas.

Para verificar si un servicio existe se usa `Services::has` (se envía como argumento el nombre del servicio) y `Services::names` devuelve un array con los nombres de todos los servicios disponibles.

```
require __DIR__.'/vendor/autoload.php';

use rguezque\{Group, Katya, Request, HtmlResponse, Services, ViewEngine};

$router = new Katya;
$services = new Services;

// Ejemplo de registro eficiente de un servicio
$services->register('view', static function() {
    static $view = null;
    if ($view === null) {
        $view = new ViewEngine(
            templates_dir: __DIR__.'/views',
            cache_dir: __DIR__.'/views/cache'
        );
    }
    return $view;
});
$services->register('is_pair', function(int $number) {
    return $number % 2 == 0;
});

$router->setServices($services);

$router->get('/', function(Request $request, Services $service) {
    $view = $service->view(); // o bien en contexto de objeto: $service->view
    return new HtmlResponse($view->fetch('home.php'));
})->useServices('view'); // Solamente recibirá el servicio 'view'
```

Variables
---------

[](#variables)

Asigna variables globales dentro de la aplicación con `Katya::setVariables` que recibe como parámetro un objeto `Variables`.

```
require __DIR__.'/vendor/autoload.php';

use rguezque\{Katya, Request, Variables};

$router = new Katya;
$vars = new Variables;

$vars->set('pi', 3.141592654);
$router->setVariables($vars);

$router->route(Katya::GET, '/', function(Request $request, Variables $vars) {
    $response->send($vars->get('pi'));
});
```

Con `Variables::set` se crea una variable, recibe como parámetros el nombre de la variable y su valor.

```
$vars->set('pi', 3.141592654);
```

Recupera una variable con el método `Variables::get`, recibe como parámetros el nombre de la variable y un valor default en caso de que la variable llamada no exista; este último parámetro es opcional y si no se declara devolverá un valor `null` por default.

```
$vars->get('pi'); // Devuelve la variable pi (si no existe devuelve null)
$vars->get('pi', 3.14) // Devuelve la variable pi (si no existe devuelve por default el valor 3.14)
```

Para verificar si una variable existe se utiliza el método `Variables::has` que devolverá `true` si la variable existe o `false` en caso contrario.

```
$vars->has('pi') // Para este ejemplo devolvería TRUE
```

Important

Todos los nombres de variables son normalizados a minúsculas y son enviadas siempre como último argumento en cada controlador; solo si se han definido y asignado con `Katya::setVariables`.

DB Connection
-------------

[](#db-connection)

La clase `DbConnection` proporciona el medio para crear una conexión *singleton* con MySQL o sqlite [Ver SQLite connection](#sqlite-connection) a través del driver `PDO` o la clase `mysqli`. El método estático `DbConnection::getConnection` recibe los parámetros de conexión y devuelve un objeto con la conexión creada. Los valores posibles para `driver` son: `pdomysql`, `mysqli` o `pdo_sqlite`.

```
use rguezque\DbConnection;

$db = DbConnection::getConnection([
    'driver' => 'pdomysql',
    'host' => 'localhost',
    'port' => 3306,
    'user' => 'root',
    'pass' => 'mypassword',
    'db_name' => 'mydatabase'
    'charset' => 'utf8'
]);

$db = DbConnection::getConnection([
    'driver' => 'mysqli',
    'host' => 'localhost',
    'port' => 3306,
    'user' => 'root',
    'pass' => 'mypassword',
    'db_name' => 'mydatabase'
    'charset' => 'utf8',
]);
```

Note

Para el caso de conexiones con `PDO`, si se utiliza un *socket* define el parámetro `socket` que por lo regular es `/var/run/mysqld/mysqld.sock` o en el caso de XAMPP es `/opt/lampp/var/mysql/mysql.sock`; los parámetros `host` y `port` serán ignorados aunque hayan sido definidos.

Para conexiones con `mysqli` el parámetro `socket` determinará el tipo de conexión aunque se haya definido `host`.

### Connecting using an URL

[](#connecting-using-an-url)

Otra alternativa es usar una *database URL* como parámetro de conexión, a través del método estático `DbConnection::dsnParser`; este recibe una URL y la procesa para ser enviada a `DbConnection::getConnection` de la siguiente forma:

```
use rguezque\DbConnection;

// Con mysqli
// 'mysqli://root:mypassword@127.0.0.1/mydatabase?charset=utf8'
// Con PDO
$connection_params = DbConnection::dsnParser('pdomysql://root:mypassword@127.0.0.1/mydatabase?charset=utf8');
$db = DbConnection::getConnection($connection_params);
```

### Auto connect

[](#auto-connect)

El método estático `DbConnection::autoConnect` crea y devuelve una conexión singleton a MySQL tomando automáticamente los parámetros definidos en un archivo `.env`. Solo aplica para `pdomysql` y `mysqli`.

```
use rguezque\DbConnection;

$db = DbConnection::autoConnect();
```

El archivo `.env` debería verse mas o menos así:

```
DB_DRIVER="mysqli"
DB_NAME="mydatabase"
DB_HOST="127.0.0.1"
DB_PORT=3306
DB_USER="root"
DB_PASS="mypassword"
DB_CHARSET="utf8"

```

Note

Se debe usar alguna librería que permita procesar la variables almacenadas en `.env` y cargarlas en las variables `$_ENV`. La más usual es `vlucas/phpdotenv`.

### Create new instances

[](#create-new-instances)

Para crear nuevas instancias de conexión `PDO` o `mysqli` utiliza el método `DbConnection::create()`, este devolverá una nueva instancia de conexión cada vez que se invoque con diferentes valores de conexión. Este método recibe los mismos parámetros que `DbConnection::getConnection()`.

### SQLite connection

[](#sqlite-connection)

Para crear una conexión sqlite debes definir el parámetro `driver` como `pdo_sqlite` y definir el parámetro `db_file` con la ruta completa al archivo `.sqlite`. Si el archivo no existe, se intentará crear automáticamente.

```
// Singleton
DbConnection::getConnection([
    'driver' => 'pdo_sqlite',
    'db_file' => __DIR__.'/storage/database.sqlite',
    'charset' => 'utf8'
]);

//Nueva instancia
$db = DbConnection::create([
    'driver' => 'pdo_sqlite',
    'db_file' => __DIR__.'/storage/database2.sqlite',
    'charset' => 'utf8'
]);
```

Note

Si se omite el parámetro `db_file` se creará una conexión en memoria `:memory:` automáticamente.

Middleware
----------

[](#middleware)

El *middleware* `Route::before` ejecuta una o varias acciones previas al controlador de una ruta.

`Route::before` Recibe uno o varios objetos `callable` (función, método de objeto o método estático) donde se definen las acciones a ejecutar, este objeto a su vez recibe los mismos parámetros que los controladores: obligatoriamente un objeto `Request` y en orden de prioridad, `Services` y `Variables` según hayan sido definidos. Y además recibe como último argumento una función que representa el siguiente middleware en la cadena o, finalmente, el controlador. Para continuar el flujo, el middleware debe invocarse con los mismos argumentos que reciben los controladores. Ej: `return $next($request, $services, ...)`.

Los middlewares de grupo se heredan, pero los definidos en rutas individuales tienen prioridad y no son sobreescritos.

```
require __DIR__.'/vendor/autoload.php';

use rguezque\{Group, Katya, Request, Response, Session};

$router = new Katya;

$router->get('/', function(Request $request) {
    $data = $request->getParams();
    $username = $data->get('@middleware_data');
    return new Response(sprintf('The actual user is: %s', $username));
})->before(function(Request $request, $next) {
    $session = Session::select('mi_sesion');
    if(!$session->has('logged')) {
        // Ejecuta el response y detiene el router
        Katya::halt(new Response(headers: ['location' => '/login']));
    }
    // Puedes pasar datos al controlador usando parámetros
    $request->setParams(['@middleware_data' => $session->get('username')]);

    return $next($request);
});
```

Note

- Los middlewares se ejecutan en orden inverso de definición (LIFO) y cada uno debe invocar `$next` para continuar la cadena.
- Los middlewares de grupo se heredan, pero los definidos en rutas individuales tienen prioridad y no son sobreescritos.
- Si el middleware es una instancia de clase, esta clase debe definir las acciones del propio middlewae en el método `__invoke()`

CORS
----

[](#cors)

*(Cross-Origin Resource Sharing)*. Esta configuración se define a través de un objeto `CorsConfig` en el cual se agregan los origenes, los métodos de petición permitidos para cada *origen* así como los encabezados http aceptados, el tiempo en segundos para la *cache* de las *preflight requests* y soporte para credenciales de acceso.

```
require __DIR__.'/vendor/autoload.php';

use rguezque\Katya;
use rguezque\CorsConfig;

$router = new Katya;
$cors_config = new CorsConfig();

$cors_config->addOrigin(
    'https://example.com',
    ['GET', 'POST'],
    [
        'allowed_headers' => ['Content-Type', 'Authorization'],
        'supports_credentials' => true
    ]
);

$cors_config->addOrigin(
    '(http(s)://)?(www\.)?localhost:4500', // También soporta regex
    ['GET', 'POST', 'DELETE'],
    [
        'allowed_headers' => ['Content-Type'],
        'max_age' => 3600 // 1 hora
    ]
);
```

Los métodos y configuración http son opcionales; por default para todos los origenes todos los métodos son aceptados y la configuración default es la siguiente:

```
[
    'allowed_headers' => ['Content-Type', 'Authorization'],
    'max_age' => 86400, // 24 horas
    'supports_credentials' => false
]
```

Asigna la configuración de CORS con el método `Katya::setCors` y automaticamente se ejecutará al correr el router:

```
// Se asigna al router
$router->setCors($cors_config);
```

Environment Management
----------------------

[](#environment-management)

`Environment::register` inicializa el ambiente de desarrollo y puede recibir el argumento `development` o `production`. Si se invoca sin argumento buscará cargar automáticamente desde la variable `APP_ENV` del archivo `.env`; en caso de no encontrarla se tomará por default el modo `development`.

```
// Se define directamente el ambiente de desarrollo
Environment::register('production');

// O busca automáticamente la variable de ambiente APP_ENV
Environment::register();
```

`Environment::setLogPath` especifica el directorio (obligatorio) donde se guardará el registro de errores. Todos los errores que ocurran en ambos ambientes de desarrollo se volcarán en un archivo `php_errors.log`.

```
// Por ejemplo
Environment::setLogPath(__DIR__.'/path/to/custom/logs');
```

Usa `Environment::getLogPath` para recuperar la ruta completa del archivo de registro de errores.

Note

Asegurate de definir tu zona horaria previamente con `set_default_timezone_set('America/Mexico_City')` de lo contrario los *logs* mostrarán la fecha en `GMT` (Greenwich Mean Time) por default.

helpers
-------

[](#helpers)

Se incluye también algunas funciones extras bajo el namespace `\rguezque\functions\`:

- `env(string $key, mixed $default = null, ?int $cast_to = null)`: Esta función devuelve el valor de una variable de entorno. si la variable no existe, devuelve el valor default especificado. Si se especifica el tercer argumento casteará la variable al tipo de dato especificado entre los disponibles `CAST_INT`, `CAST_STR`, `CAST_FLOAT`, `CAST_ARRAY`, `CAST_BOOL`, `CAST_OBJECT`.
- `equals(string $str_one, string $str_two)`: Compara dos cadenas de texto y devuelve si `true` si son iguales; `false` en caso contrario.
- `unsetcookie(string $name)`: Elimina una cookie.
- `getcookie(string $name, $default = null)`: Devuelve una cookie por nombre, si no existe devuelve el valor default especificado.
- `json_file_get_contents(string $file)`: Recupera el contenido de un archivo `.json` y lo devuelve como un array asociativo.
- `is_assoc_array($value)`: Devuelve `true` si un array es asociativo (key-value): `false` en caso contrario.
- `add_trailing_slash(string $str)`: Agrega un *slash* al final de una cadena de texto.
- `remove_trailing_slash(string $str)`: Elimina los *slashes* al final de una cadena de texto.
- `add_leading_slash(string $str)`: Agrega un *slash* al inicio de una cadena de texto.
- `remove_leading_slash(string $str)`: Elimina los *slashes* al inicio de una cadena de texto.
- `str_prepend(string $subject, string ...$prepend)`: Concatena una o más cadenas de texto al inicio de una cadena de texto original. Los elementos se concatenan siguiendo el orden **FIFO** (el primero que se define es el primero que se concatena al inicio y así sucesivamente). Ej: `str_prepend("foo", "bar", "baz")` daría como resultado `"bazbarfoo"`.
- `str_append(string $subject, string ...$append)`: Concatena una o más cadenas de texto al final de una cadena de texto original. Al igual que `str_prepend` sigue el orden **FIFO**.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance71

Regular maintenance activity

Popularity13

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~112 days

Recently: every ~103 days

Total

8

Last Release

165d ago

Major Versions

1.3.0 → v2.0.02025-11-28

PHP version history (3 changes)1.0PHP &gt;=7.4.0

1.1.0PHP &gt;=8.1.9

v2.0.0PHP &gt;=8.2.12

### Community

Maintainers

![](https://www.gravatar.com/avatar/cff6726075cd59f732d23d14c33f7d11c3402fb75c554bcfb0abd16c4f559415?d=identicon)[rguezque](/maintainers/rguezque)

---

Top Contributors

[![rguezque](https://avatars.githubusercontent.com/u/23480766?v=4)](https://github.com/rguezque "rguezque (165 commits)")

---

Tags

microframeworkmvcmvc-patternphprouterouterroutingrouting-enginephprouterroutingmvcmicroframework

### Embed Badge

![Health badge](/badges/rguezque-katya-router/health.svg)

```
[![Health](https://phpackages.com/badges/rguezque-katya-router/health.svg)](https://phpackages.com/packages/rguezque-katya-router)
```

###  Alternatives

[leafs/leaf

Elegant PHP for modern developers

1.3k44.3k9](/packages/leafs-leaf)[vlucas/bulletphp

A heierarchical resource-oriented micro-framework built on nested closures instead of route-based callbacks

41949.9k1](/packages/vlucas-bulletphp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
