PHPackages                             kissous/attribute-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. [HTTP &amp; Networking](/categories/http)
4. /
5. kissous/attribute-router

ActiveLibrary[HTTP &amp; Networking](/categories/http)

kissous/attribute-router
========================

The compiled PHP 8 attribute router.

v1.0.0(1mo ago)11MITPHPPHP &gt;=8.3CI passing

Since Jun 1Pushed 1mo agoCompare

[ Source](https://github.com/Kissous/attribute-router)[ Packagist](https://packagist.org/packages/kissous/attribute-router)[ Docs](https://github.com/Kissous/attribute-router)[ RSS](/packages/kissous-attribute-router/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (6)Versions (2)Used By (0)

attribute-router
================

[](#attribute-router)

> The compiled PHP 8 attribute router.

Declare routes with `#[Route]` attributes on controller methods. They are scanned once and compiled into a static PHP dispatch table — **zero runtime reflection, zero external dependencies**, PSR-7 compatible.

A lightweight option for small projects that want attribute routing without pulling in a framework or a larger routing component.

- **Compiled** — scanning and regex assembly happen once, at build time.
- **Zero runtime reflection** — dispatch is array lookups plus `preg_match`.
- **Zero dependencies** — only the PSR HTTP message interfaces.
- **Minimal API** — three classes you actually touch: the attribute, the CLI, the dispatcher.

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

[](#requirements)

- PHP 8.3+
- Any [PSR-7](https://www.php-fig.org/psr/psr-7/) implementation for the request object (e.g. `nyholm/psr7`).

Install
-------

[](#install)

```
composer require kissous/attribute-router
```

Quick start
-----------

[](#quick-start)

### 1. Declare routes

[](#1-declare-routes)

```
use Kissous\AttributeRouter\Attribute\Route;

final class UserController
{
    #[Route('/users', method: 'GET', name: 'user.index')]
    public function index(): string
    {
        return 'all users';
    }

    #[Route('/users/{id}', method: 'GET', name: 'user.show')]
    public function show(string $id): string
    {
        return "user #{$id}";
    }
}
```

A parameter `{id}` matches a single path segment (`[^/]+`) and is passed to the method by name.

### 2. Compile once (build step)

[](#2-compile-once-build-step)

```
vendor/bin/attribute-router compile --scan=src/Controller --out=var/routes.compiled.php
```

Pass `--scan` more than once to scan several directories. Run this in your build / deploy pipeline (and locally after changing routes); the generated file is a plain `return [...]` array that the dispatcher loads with `require`.

### 3. Dispatch at runtime

[](#3-dispatch-at-runtime)

```
use Kissous\AttributeRouter\Dispatcher\Dispatcher;

$dispatcher = Dispatcher::fromCompiledFile(__DIR__ . '/var/routes.compiled.php');

$result = $dispatcher->dispatch($request); // any PSR-7 ServerRequestInterface

if ($result->isNotFound()) {
    http_response_code(404);
    return;
}

if ($result->isMethodNotAllowed()) {
    http_response_code(405);
    header('Allow: ' . implode(', ', $result->allowedMethods));
    return;
}

// Matched: $result->controller, $result->action, $result->parameters, $result->name
$controller = new ($result->controller)();
echo $controller->{$result->action}(...$result->parameters);
```

`$result->parameters` is keyed by parameter name, so spreading it (`...`) passes them as named arguments — order-independent and matching the method signature. Swap the `new (...)` line for your DI container when you have one.

The `DispatchResult`
--------------------

[](#the-dispatchresult)

`Dispatcher::dispatch()` returns an immutable `DispatchResult`:

PropertyTypeMeaning`status``DispatchStatus``Found` / `NotFound` / `MethodNotAllowed``controller``?string`matched controller FQCN (match only)`action``?string`matched method name (match only)`parameters``array`captured route parameters (match only)`name``?string`route name, if declared (match only)`allowedMethods``list`allowed methods (method-not-allowed only)Helpers: `isFound()`, `isNotFound()`, `isMethodNotAllowed()`.

How it works
------------

[](#how-it-works)

```
scan  ──►  compile  ──►  dispatch

```

`ClassScanner` reads `#[Route]` attributes via reflection and emits `ScannedRoute` DTOs. `Compiler` turns them into a readable, closure-free PHP file (static paths in a direct-lookup map, dynamic paths as anchored regexes). `Dispatcher` loads that file and resolves a request with array lookups and `preg_match` only. All reflection is confined to the scanner and runs at build time. See [docs/architecture.md](docs/architecture.md).

FAQ
---

[](#faq)

**Does it use reflection at runtime?** No. Reflection is confined to the scanner and runs only when you compile.

**What dependencies does it pull in?** Only the PSR HTTP message interfaces.

**Do I have to recompile after changing routes?** Yes — re-run the `compile`command. Wire it into your build step; in development, run it whenever routes change.

**Can I commit the compiled file?** You can, but it is typically a build artifact written to `var/` and gitignored.

**Is it a full framework / does it call my controller?** No. It resolves a request to a controller, action and parameters; you instantiate and invoke (directly or through your container), keeping it framework-agnostic.

**What about route constraints, `#[Get]` aliases, URL generation, middleware?**Planned for later minor versions — see the roadmap in `docs/roadmap/`.

Lightweight by design
---------------------

[](#lightweight-by-design)

The design trades a build step for a cheap runtime: no reflection, no attribute parsing, no object graph — just a map lookup and, for dynamic routes, a single `preg_match`. The aim is a small, dependency-free router that is easy to drop into a small project, not a replacement for full-featured routers.

Development
-----------

[](#development)

```
composer install
composer test          # unit + integration
composer stan          # PHPStan (max level)
composer cs:check      # PHP-CS-Fixer dry-run
```

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance89

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 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

Unknown

Total

1

Last Release

53d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20760536?v=4)[Kissous Omar](/maintainers/Kissous)[@Kissous](https://github.com/Kissous)

---

Top Contributors

[![Kissous](https://avatars.githubusercontent.com/u/20760536?v=4)](https://github.com/Kissous "Kissous (14 commits)")

---

Tags

attributescompiledcontrollerhttp-routerlightweightphpphp-attributesphp8psr-7routerroutingzero-dependencypsr-7routerroutingcompiledattributeslightweightphp8

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/kissous-attribute-router/health.svg)

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

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

7.9k1.1B4.1k](/packages/guzzlehttp-psr7)[aura/router

Powerful, flexible web routing for PSR-7 requests.

5221.6M69](/packages/aura-router)[sunrise/http-router

A powerful solution as the foundation of your project.

17451.8k11](/packages/sunrise-http-router)

PHPackages © 2026

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