PHPackages                             scriptmancer/piri - 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. scriptmancer/piri

ActiveLibrary[Framework](/categories/framework)

scriptmancer/piri
=================

A modern, attribute-based PHP router with powerful features for building web applications

v0.9.6(1y ago)07MITPHPPHP ^8.1

Since Feb 17Pushed 1y ago1 watchersCompare

[ Source](https://github.com/scriptmancer/piri)[ Packagist](https://packagist.org/packages/scriptmancer/piri)[ RSS](/packages/scriptmancer-piri/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (6)Versions (4)Used By (0)

Piri Router
===========

[](#piri-router)

A lightweight, attribute-based PHP router with support for middleware, route groups, and parameter validation.

Features
--------

[](#features)

- Attribute-based routing for clean controller definitions
- Support for route parameters with regex pattern validation
- Middleware support (global, group, and route-specific)
- Route groups for organizing related routes
- Named routes for easy URL generation
- Namespace-based controller registration
- Type conversion for route parameters
- PSR-7 compatible

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

[](#installation)

```
composer require yourusername/piri-router
```

Basic Usage
-----------

[](#basic-usage)

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

use Piri\Core\Router;
use Piri\Attributes\Route;

// Create a new router instance
$router = new Router();

// Register a controller
$router->registerClass(HomeController::class);

// Define a route using a closure
$router->get('/', function() {
    return 'Hello, World!';
});

// Run the router
$router->run();
```

Controller Example
------------------

[](#controller-example)

```
use Piri\Attributes\Route;

class HomeController
{
    #[Route('/')]
    public function index(): string
    {
        return 'Welcome to the homepage!';
    }

    #[Route('/about')]
    public function about(): string
    {
        return 'About us page';
    }
}
```

Route Patterns
--------------

[](#route-patterns)

You can use regex patterns in your route parameters:

```
// Numeric ID parameter
#[Route('/users/{id:\d+}')]
public function numericId(array $params): string
{
    // The id parameter will only match digits
    $id = $params['id']; // Will be a string of digits
    return 'User ID: ' . $id;
}

// Alphabetic username parameter
#[Route('/users/{username:[a-zA-Z]+}')]
public function alphaUsername(array $params): string
{
    // The username parameter will only match letters
    $username = $params['username']; // Will be a string of letters
    return 'Username: ' . $username;
}

// Using method calls
$router->get('/posts/{id:\d+}', function(array $params) {
    $id = $params['id'];
    return 'Post ID: ' . $id;
});
```

### Handling Route Parameters

[](#handling-route-parameters)

All route parameters are passed to your handler method as a single array. You should always define your handler method to accept an array parameter, and then access the route parameters from that array:

```
#[Route('/users/{id}/posts/{postId?}')]
public function posts(array $params): array
{
    // Access parameters from the $params array
    $id = $params['id'];
    $postId = $params['postId'] ?? null; // Use null coalescing for optional parameters

    return [
        'user' => $id,
        'post' => $postId
    ];
}
```

Route Groups
------------

[](#route-groups)

You can group routes together using the `RouteGroup` attribute on controller classes:

```
#[RouteGroup(prefix: '/api', name: 'api', middleware: [ApiAuthMiddleware::class])]
class ApiController
{
    #[Route('/users', name: 'users.list')]
    public function listUsers(): array
    {
        // This route will be accessible at /api/users
        // It will have the middleware ApiAuthMiddleware applied
        // Its name will be api.users.list
        return ['users' => []];
    }

    #[Route('/users/{id:\d+}')]
    public function getUser(array $params): array
    {
        // This route will be accessible at /api/users/{id}
        // It will also have the middleware ApiAuthMiddleware applied
        return ['user' => ['id' => $params['id']]];
    }
}
```

Namespace Registration
----------------------

[](#namespace-registration)

You can register all controllers in a namespace at once:

```
// Register all controllers in the App\Controller namespace
$router->registerNamespace('App\Controller');

// Register with prefix, name, and middleware
$router->registerNamespace(
    'App\Api\Controller',
    prefix: '/api',
    name: 'api',
    middleware: [ApiAuthMiddleware::class]
);
```

This will automatically register all controllers in the specified namespace and apply the prefix, name, and middleware to all routes in those controllers.

Middleware
----------

[](#middleware)

Middleware allows you to filter HTTP requests entering your application:

```
// Define a middleware class
class AuthMiddleware implements MiddlewareInterface
{
    public function handle(callable $next, array $parameters = []): mixed
    {
        // Check if user is authenticated
        if (!isset($_SESSION['user'])) {
            http_response_code(401);
            return 'Unauthorized';
        }

        // Call the next middleware or the route handler
        return $next($parameters);
    }
}

// Apply middleware globally
$router->addGlobalMiddleware(new LoggingMiddleware());

// Apply middleware to a group
$router->group(['prefix' => '/admin', 'middleware' => [new AuthMiddleware()]], function($router) {
    $router->get('/dashboard', [AdminController::class, 'dashboard']);
});

// Apply middleware to a specific route
$router->get('/profile', [UserController::class, 'profile'],
    middleware: [new AuthMiddleware()]);

// Apply middleware using attributes
#[Route('/settings', middleware: [AuthMiddleware::class])]
public function settings(): string
{
    return 'Settings page';
}
```

Error Handling
--------------

[](#error-handling)

You can customize error handling by providing an error handler function to the `handle` method:

```
// Custom error handling
$router->handle([
    'error_handler' => function(\Exception $e) {
        if ($e instanceof RouteNotFoundException) {
            http_response_code(404);
            include 'templates/404.php';
        } else {
            http_response_code(500);
            error_log($e->getMessage());
            include 'templates/500.php';
        }
    }
]);
```

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

[](#advanced-usage)

For more advanced usage, including route caching, custom request handling, and more, please refer to the [Documentation](DOCUMENTATION.md).

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

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements
----------------

[](#acknowledgements)

- Inspired by modern PHP routing libraries
- Built with PHP 8.1+ features in mind

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance44

Moderate activity, may be stable

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

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

Total

3

Last Release

438d ago

### Community

Maintainers

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

---

Top Contributors

[![gsarigul84](https://avatars.githubusercontent.com/u/1032251?v=4)](https://github.com/gsarigul84 "gsarigul84 (5 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/scriptmancer-piri/health.svg)

```
[![Health](https://phpackages.com/badges/scriptmancer-piri/health.svg)](https://phpackages.com/packages/scriptmancer-piri)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.3k86.3M2.2k](/packages/symfony-symfony)[cakephp/cakephp

The CakePHP framework

8.8k18.5M1.6k](/packages/cakephp-cakephp)[silverstripe/framework

The SilverStripe framework

7213.5M2.5k](/packages/silverstripe-framework)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)[cakephp/authentication

Authentication plugin for CakePHP

1153.6M67](/packages/cakephp-authentication)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)

PHPackages © 2026

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