PHPackages                             willy68/pg-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. willy68/pg-router

ActiveLibrary[Framework](/categories/framework)

willy68/pg-router
=================

A fast, flexible, and PSR-7 compatible router for PHP.

2.0.6(10mo ago)016MITPHPPHP ~8.1 || ~8.2 || ~8.3 || ~8.4CI passing

Since May 29Pushed 10mo ago1 watchersCompare

[ Source](https://github.com/willy68/pg-router)[ Packagist](https://packagist.org/packages/willy68/pg-router)[ RSS](/packages/willy68-pg-router/feed)WikiDiscussions main Synced today

READMEChangelog (10)Dependencies (14)Versions (19)Used By (0)

pg-router
=========

[](#pg-router)

[![Latest Stable Version](https://camo.githubusercontent.com/3d68ca095da60c20b59cec584950a2c9a5ea21e1e880d71f55cfeb210d776583/687474703a2f2f706f7365722e707567782e6f72672f77696c6c7936382f70672d726f757465722f76)](https://packagist.org/packages/willy68/pg-router)[![Total Downloads](https://camo.githubusercontent.com/4004b3868e0c225d75503606f3182cae49fbc671635a856a1012a588f9e259b6/687474703a2f2f706f7365722e707567782e6f72672f77696c6c7936382f70672d726f757465722f646f776e6c6f616473)](https://packagist.org/packages/willy68/pg-router)[![Latest Unstable Version](https://camo.githubusercontent.com/61f46973707b280803838b4c5080d67970f39a902c24de43cffb3e92182c2cf7/687474703a2f2f706f7365722e707567782e6f72672f77696c6c7936382f70672d726f757465722f762f756e737461626c65)](https://packagist.org/packages/willy68/pg-router)[![License](https://camo.githubusercontent.com/53e281fc9da9408fd345a217cac7db377b17f0abc4b6b8914600ffb17e866005/687474703a2f2f706f7365722e707567782e6f72672f77696c6c7936382f70672d726f757465722f6c6963656e7365)](https://packagist.org/packages/willy68/pg-router)[![PHP Version Require](https://camo.githubusercontent.com/67483ee76147b7c29792680ee07d5475a6776a3b64aa84efecc5a39311994431/687474703a2f2f706f7365722e707567782e6f72672f77696c6c7936382f70672d726f757465722f726571756972652f706870)](https://packagist.org/packages/willy68/pg-router)[![Coverage Status](https://camo.githubusercontent.com/a68fa1023410e0a52bc14ad43873ebbc5b0279af98ede4d223c106ac2e69ff65/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f77696c6c7936382f70672d726f757465722f62616467652e7376673f6272616e63683d6d61696e)](https://coveralls.io/github/willy68/pg-router?branch=main)[![Continuous Integration](https://github.com/willy68/pg-router/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/willy68/pg-router/actions/workflows/ci.yml)

A fast, flexible, and PSR-7 compatible HTTP router for PHP applications. Built for performance with support for advanced routing patterns, middleware stacking, and route caching.

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Credits](#credits)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Advanced Usage](#advanced-usage)
    - [Route Parameters](#route-parameters)
    - [Optional Segments](#optional-segments)
    - [Route Groups](#route-groups)
    - [Middleware](#middleware)
    - [Named Routes](#named-routes)
    - [CRUD Helper](#crud-helper)
    - [URL Generation](#url-generation)
- [Route Caching](#route-caching)
- [Performance](#performance)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)

Features
--------

[](#features)

- ✅ **PSR-7 Compatible**: Full support for PSR-7 request interfaces
- 🚀 **High Performance**: Optimized route matching with caching support
- 🎯 **Flexible Routing**: Support for complex route patterns and constraints
- 🔧 **Middleware Support**: Route-level and group-level middleware stacking
- 📦 **Route Grouping**: Organize routes with shared prefixes and middlewares
- 🎨 **Named Routes**: Easy URL generation with named route support
- ⚡ **CRUD Helpers**: Quick REST resource route generation
- 🔀 **Optional Segments**: Advanced optional route segment support
- 🏗️ **Extensible**: Custom matchers and collectors for advanced use cases

Credits
-------

[](#credits)

The regex pattern implementation and benchmarking are inspired by [nikic/Fast-Route](https://github.com/nikic/FastRoute).
For a detailed explanation of how this approach works and why it is fast, please read [nikic's blog post](http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html).

This router's implementation is original and may differ in speed or structure compared to Fast-Route.
Some parts do not strictly follow the same patterns as nikic/Fast-Route.

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Composer

Installation
------------

[](#installation)

Install via Composer:

```
composer require willy68/pg-router
```

Quick Start
-----------

[](#quick-start)

```
use Pg\Router\Router;
use guzzlehttp\Psr7\Response;
use guzzlehttp\Psr7\ServerRequest;

$request = ServerRequest::fromGlobals(); // Create a PSR-7 request from global variables
$router = new Router();

$router->route('/hello/{name: \w+}', function ($request): ResponseInterface {
    $name = $request->getAttribute('name');
    (return new Response())->getBody()->write("Hello, $name!");
}, 'hello', ['GET']);

$res = $router->match($request);

if ($res->isSuccess()) {
// add route attributes to the request
    foreach ($res->getMatchedAttributes() as $key => $val) {
        $request = $request->withAttribute($key, $val);
    }

$callback = $res->getMatchedRoute()->getCallback();
$response = $callback($request);
```

Advanced Usage
--------------

[](#advanced-usage)

### Route Parameters

[](#route-parameters)

```
// Simple parameter, id matches any alphanumeric string
$router->route('/user/{id}','handler', 'user.show', ['GET']);

//Define route parameters with custom patterns:
// Parameter with regex constraint
$router->route('/user/{id:\d+}','handler', 'user.show', ['GET']);

// Multiple parameters
$router->route('/blog/{year:\d{4}}/{month:\d{2}}/{slug}','handler', 'blog.post', ['GET']);
```

It is possible to define default tokens for parameters:

```
// The id matches a numeric string for this route
$route = $router->route('/user/{id}','handler', 'user.show', ['GET'])
    ->setTokens(['id' => '\d+']);

// Default token for all routes before adding a new one
$router->setTokens(['id' => '\d+']);
// Or with The Configuration in the constructor
$router = new Router(
    null,
    null,
    [Router::CONFIG_DEFAULT_TOKENS => ['id' => '[0-9]+', 'slug' => '[a-zA-Z-]+[a-zA-Z0-9_-]+']]
);

// Update and/or add tokens given by the Router
$route->updateTokens(['id' => '[0-9]+', 'slug' => '[a-zA-Z0-9_-]+']);
```

### Optional Segments

[](#optional-segments)

**Breaking Change**: Optional segments now use a new syntax with `[!...;...]` pattern:

```
// Example route with optional segments
$router->route('/article[!/{id: \d+};/{slug: [\w-]+}]', function ($request) {
    $id = $request->getAttribute('id', null);
    $slug = $request->getAttribute('slug', null);
    // ...
}, 'article.show', ['GET']);
```

This route matches:

- `/article` (no parameters)
- `/article/123` (id parameter only)
- `/article/123/my-article-title` (both id and slug parameters)

Parameters will be available in the request based on the provided segments.

### Route Groups

[](#route-groups)

Organize related routes with shared prefixes and middlewares:

```
$router->group('/api/v1', function ($group) {
    $group->route('/users', 'UserController::index', 'api.users.index', ['GET']);
    $group->route('/users/{id:\d+}', 'UserController::show', 'api.users.show', ['GET']);
    $group->route('/users', 'UserController::store', 'api.users.store', ['POST']);
})->middlewares([AuthMiddleware::class, ApiMiddleware::class]);
```

### Middleware

[](#middleware)

Apply middleware to individual routes or groups:

```
// Route-level middleware
$router->route('/admin/dashboard','handler', 'admin.dashboard', ['GET'])
    ->middlewares([AuthMiddleware::class, AdminMiddleware::class]);

// Group-level middleware
$router->group('/admin', function ($group) {
    $group->route('/users', 'AdminController::users', 'admin.users', ['GET']);
    $group->route('/settings', 'AdminController::settings', 'admin.settings', ['GET']);
})->middlewares([AuthMiddleware::class, AdminMiddleware::class]);
```

### Named Routes

[](#named-routes)

Generate URLs using named routes:

```
// Define a named route
$router->route('/user/{id:\d+}','handler', 'user.profile', ['GET']);

// Generate URL
$url = $router->generateUri('user.profile', ['id' => 123]);
// Result: /user/123

// Generate URL with query parameters
$url = $router->generateUri('user.profile', ['id' => 123], ['tab' => 'settings']);
// Result: /user/123?tab=settings
```

### CRUD Helper

[](#crud-helper)

```
$router->crud('/posts', PostController::class, 'posts');
```

This creates the following routes:

- `GET /posts` → `PostController::index` (posts.index)
- `GET /posts/new` → `PostController::create` (posts.create)
- `POST /posts/new` → `PostController::create` (posts.create.post)
- `GET /posts/{id:\d+}` → `PostController::edit` (posts.edit)
- `POST /posts/{id:\d+}` → `PostController::edit` (posts.edit.post)
- `DELETE /posts/{id:\d+}` → `PostController::delete` (posts.delete)

### URL Generation

[](#url-generation)

```
// Basic URL generation
$url = $router->generateUri('hello', ['name' => 'Alice']);
// With query parameters
$url = $router->generateUri('user.profile', ['id' => 123], ['tab' => 'settings']);
```

Route Caching
-------------

[](#route-caching)

Enable route caching for production environments:

```
// Enable caching with a cache file
      $router = new Router (
           null,
           null,
           [
               Router::CONFIG_CACHE_ENABLED => ($env === 'prod'),
               Router::CONFIG_CACHE_DIR => '/tmp/cache',
               Router::CONFIG_CACHE_POOL_FACTORY => function (): CacheItemPoolInterface {...},
           ]
      )

// In production, routes are cached and loaded from the cache file
// In development, disable caching or clear cache when routes change
$router->clearCache();
```

`Router::CONFIG_CACHE_POOL_FACTORY` allows you to use a custom PSR-6 compatible cache pool implementation,
but this parameter is optional.

### Using FileCache with Regex Collector

[](#using-filecache-with-regex-collector)

The `FileCache` class provides a simple file-based caching solution that works well with all regex collectors.

Here's a practical example of using `FileCache` with route collectors:

```
use Pg\Router\Cache\FileCache;
use Pg\Router\RegexCollector\MarkRegexCollector;
use Pg\Router\RegexCollector\NamedRegexCollector;
use Pg\Router\RegexParser\FastMarkParser;

// Initialize the cache with a custom directory
$fileCache = new FileCache(
    cacheDir: __DIR__ . '../tmp/cache/router',  // Directory to store cache files
    useCache: true                                // Enable caching
);

// Example of using the cache with a route collection
$collectors = [
    'MarkRegexCollector' => new MarkRegexCollector(),
    'NamedCollector' => new NamedRegexCollector(),
    'FastMarkCollector' => new MarkRegexCollector(new FastMarkParser()),
    // Add other collectors if needed
];

// Sample routes
$allRoutes = [
    // Your route definitions here
];

foreach ($collectors as $name => $collector) {
    $collector->addRoutes($allRoutes);
    $hasCache = $fileCache->has($name);

    // Fetch data with caching
    // The callback will only execute if the cache is empty
    $startTime = microtime(true);
    $routesData = $fileCache->fetch($name, [$collector, 'getData']);
    $duration = microtime(true) - $startTime;

    echo "Collector: $name";
    echo "";
    echo "Execution time: " . number_format($duration * 1000, 4) . " ms";
    echo "Cached: " . ($hasCache ? 'Yes' : 'No') . "";
    echo "";
}

// Clear specific cache if needed
// $fileCache->delete('MarkRegexCollector');

// Or clear all caches
// $fileCache->clear();
```

In this example:

1. We create a `FileCache` instance pointing to a cache directory
2. We set up all available Collectors for route collection
3. We use `fetch()` which will return cached data if available, or execute the callback to generate and cache the data
4. We measure and display the execution time to demonstrate the performance benefit of caching

The `fetch()` method is particularly useful as it handles both the cache check and the callback execution in one call, making your code cleaner and more efficient.

Using the returned data directly in a Matcher like:

```
$data = $fileCache->fetch($name, [$collector, 'getData']);
$matcher = new \Pg\Router\Matcher\MarkDataMatcher($data);
$matches = $matcher->match('/post/{id: \d+}', 'GET');
```

Performance
-----------

[](#performance)

pg-router is designed for high performance:

- **Optimized Route Matching**: Uses efficient algorithms for route compilation and matching
- **Route Caching**: Cache compiled routes for production use
- **Minimal Memory Footprint**: Efficient memory usage for large route tables
- **Fast Parameter Extraction**: Optimized parameter extraction from matched routes

Testing
-------

[](#testing)

This project uses [PHPUnit](https://phpunit.de/) for testing. To run the tests, ensure you have PHPUnit installed via Composer:

```
# Run all tests
./vendor/bin/phpunit

# Run tests with coverage
php -dxdebug.mode=coverage ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage
# or
composer run coverage

# Run specific test file
./vendor/bin/phpunit tests/RouterTest.php
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please follow these guidelines:

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

Please ensure your code follows PSR-12 coding standards and includes appropriate tests.

License
-------

[](#license)

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

**Author**: William Lety **Maintainer**: [willy68](https://github.com/willy68)**Repository**: [pg-router](https://github.com/willy68/pg-router)

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance54

Moderate activity, may be stable

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity63

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 ~5 days

Total

17

Last Release

314d ago

Major Versions

v1.0.9 → v2.0.02025-07-10

PHP version history (2 changes)v1.0.0PHP ~8.0.0 || ~8.1.0 || ~8.2.0

v1.0.2PHP ~8.1 || ~8.2 || ~8.3 || ~8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/6ee0f14e65474268155360744e058f5a000e5d865d1e07211241554d89f792a5?d=identicon)[willy68](/maintainers/willy68)

---

Top Contributors

[![willy68](https://avatars.githubusercontent.com/u/34144331?v=4)](https://github.com/willy68 "willy68 (214 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/willy68-pg-router/health.svg)

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

###  Alternatives

[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k15](/packages/tempest-framework)[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[cakephp/cakephp

The CakePHP framework

8.9k19.5M1.8k](/packages/cakephp-cakephp)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M574](/packages/shopware-core)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)[moonshine/moonshine

Laravel administration panel

1.3k253.1k81](/packages/moonshine-moonshine)

PHPackages © 2026

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