PHPackages                             inroutephp/inroute - 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. [API Development](/categories/api)
4. /
5. inroutephp/inroute

ActiveLibrary[API Development](/categories/api)

inroutephp/inroute
==================

Generate http routing and dispatching middleware from docblock annotations

1.1.1(6y ago)21182UnlicensePHPPHP &gt;=7.2

Since Dec 10Pushed 6y ago1 watchersCompare

[ Source](https://github.com/inroutephp/inroute)[ Packagist](https://packagist.org/packages/inroutephp/inroute)[ Docs](https://github.com/inroutephp/inroute)[ RSS](/packages/inroutephp-inroute/feed)WikiDiscussions master Synced 2w ago

READMEChangelogDependencies (11)Versions (13)Used By (2)

[![Inroute](res/logo.png "Inroute")](res/logo.png)
==================================================

[](#)

[![Packagist Version](https://camo.githubusercontent.com/b7894d6f1445eae28c1906bf9b8886bb3a1fca7898a139b8ce79554bd3c541d6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696e726f7574657068702f696e726f7574652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/inroutephp/inroute)[![Build Status](https://camo.githubusercontent.com/ec1b161e4fea805abc1a1c246164d7329ec69fde8ca11f03dcb41c4ffd858ac3/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f696e726f7574657068702f696e726f7574652f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/inroutephp/inroute)[![Quality Score](https://camo.githubusercontent.com/010bb1ab9875a7374c5014baee1d582bf5cad986246a118b9e92e3fb34b6758a/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f696e726f7574657068702f696e726f7574652e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/inroutephp/inroute)

Generate http routing and dispatching middleware from docblock annotations.

Inroute is a code generator. It scans your source tree for annotated routes and generates a [PSR-15](https://www.php-fig.org/psr/psr-15/) compliant http routing middleware. In addition all routes have a middleware pipeline of their own, making it easy to add behaviour at compile time based on custom annotations.

- See the [example-app](https://github.com/inroutephp/example-app) for a complete example.
- See [console](https://github.com/inroutephp/console) for a compiler tool for the command line.

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

[](#installation)

```
composer require inroutephp/inroute
```

Table of contents
-----------------

[](#table-of-contents)

1. [Writing routes](#writing-routes)
2. [Piping a route through a middleware](#piping-a-route-through-a-middleware)
3. [Compiling](#compiling)
4. [Dispatching](#dispatching)
5. [Generating route paths](#generating-route-paths)
6. [Creating custom annotations](#creating-custom-annotations)
7. [Processing routes using compiler passes](#processing-routes-using-compiler-passes)
8. [Handling dependencies with a DI container](#handling-dependencies-with-a-di-container)
9. [Dealing with routing errors](#dealing-with-routing-errors)

Writing routes
--------------

[](#writing-routes)

Routes are annotated using annotations, are called with a [PSR-7](https://www.php-fig.org/psr/psr-7/) request object and inroute [environment](src/Runtime%5CEnvironmentInterface.php) and are expected to return a PSR-7 response.

```
use inroutephp\inroute\Annotations\BasePath;
use inroutephp\inroute\Annotations\GET;
use inroutephp\inroute\Runtime\EnvironmentInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Laminas\Diactoros\Response\TextResponse;

/**
 * @BasePath(path="/users")
 */
class UserController
{
    /**
     * @GET(
     *     path="/{name}",
     *     name="getUser",
     *     attributes={
     *         "key": "value",
     *         "name": "overwritten by path value"
     *     }
     * )
     */
    function getUser(
        ServerRequestInterface $request,
        EnvironmentInterface $environment
    ): ResponseInterface {
        return new TextResponse(
            // the name attribute from the request path
            $request->getAttribute('name')

            // the custom route attribute
            . $request->getAttribute('key')
        );
    }
}
```

- The `method` and `path` values are self explanatory.
- A route `name` is optional, and defaults to `class:method` (in the example `UserController:getUser`).
- `Attributes` are custom values that can be accessed at runtime through the request object.
- Note that the use of Laminas diactoros as a psr-7 response implementation is used in this example, you may of course use another psr-7 implementation.

Piping a route through a middleware
-----------------------------------

[](#piping-a-route-through-a-middleware)

Each route has a [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware pipeline of its own. Adding a middleware to a route can be done using the `@Pipe` annotation. In the following example the `pipedAction` route is piped through the `AppendingMiddleware` and the text `::Middleware` is appended to the route response.

```
use inroutephp\inroute\Annotations\Pipe;

class PipedController
{
    /**
     * @GET(path="/piped")
     * @Pipe(middlewares={"AppendingMiddleware"})
     */
    function pipedAction(
        ServerRequestInterface $request,
        EnvironmentInterface $environment
    ): ResponseInterface {
        return new TextResponse('Controller');
    }
}

use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AppendingMiddleware implements MiddlewareInterface
{
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ): ResponseInterface {
        $response = $handler->handle($request);

        return new TextResponse(
            $response->getBody()->getContents() . "::Middleware"
        );
    }
}
```

Compiling
---------

[](#compiling)

The recommended way of building a project is by using the [console](https://github.com/inroutephp/console) build tool. Compiling from pure php involves setting up the compiler something like the following.

```
use inroutephp\inroute\Compiler\CompilerFacade;
use inroutephp\inroute\Compiler\Settings\ArraySettings;

$settings = new ArraySettings([
    'source-classes' => [
        UserController::CLASS,
        PipedController::CLASS,
    ],
    'target-namespace' => 'example',
    'target-classname' => 'HttpRouter',
]);

$facade = new CompilerFacade;

$code = $facade->compileProject($settings);

eval($code);

$router = new example\HttpRouter;
```

Possible settings include

- `container`: The classname of a compile time container, specify if needed.
- `bootstrap`: Classname of compile bootstrap, default should normally be fine.
- `source-dir`: Directory to scan for annotated routes.
- `source-prefix`: psr-4 namespace prefix to use when scanning directory.
- `source-classes`: Array of source classnames, use instead of or togheter with directory scanning.
- `ignore-annotations`: Array of annotations to ignore during compilation
- `route-factory`: Classname of route factory, default should normally be fine.
- `compiler`: Classname of compiler to use, default should normally be fine.
- `core-compiler-passes`: Array of core compiler passes, default should normally be fine.
- `compiler-passes`: Array of custom compiler passes.
- `code-generator`: The code generator to use, default should normally be fine.
- `target-namespace`: The namespace of the generated router (defaults to no namespace).
- `target-classname`: The classname of the generated router (defaults to `HttpRouter`).

### OpenApi

[](#openapi)

> Please note that reading openapi annotations is still very rudimentary. Please open an issue if you have suggestions on more values that should be parsed.

Instead of using the built in annotations inroute is also able to build openapi projects annotated with [swagger-php](https://github.com/zircote/swagger-php)annotations.

Set the `core-compiler-passes` setting to `['inroutephp\inroute\OpenApi\OpenApiCompilerPass']`.

Dispatching
-----------

[](#dispatching)

The generated router is a [PSR-15](https://www.php-fig.org/psr/psr-15/)compliant middleware. To dispatch you need to supply an implementation of [PSR-7](https://www.php-fig.org/psr/psr-7/) for request and response objects and some response emitting functionality (of course you should also use a complete middleware pipeline for maximum power).

In this simple example we use

- [laminas-diactoros](https://github.com/laminas/laminas-diactoros) as PSR-15 implementation.
- [laminas-httphandlerrunner](https://github.com/laminas/laminas-httphandlerrunner)for emitting responses.
- The built in middleware pipeline for dispatching.

```
use inroutephp\inroute\Runtime\Middleware\Pipeline;
use Laminas\Diactoros\ServerRequestFactory;
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;

// create a simple middleware pipeline for the entire application
$pipeline = new Pipeline($router);

// create a psr-7 compliant response emitter
$emitter = new SapiEmitter;

// fakeing a GET request
$request = (new ServerRequestFactory)->createServerRequest('GET', '/users/foo');

// in the real worl you would of course use
// $request = ServerRequestFactory::fromGlobals();

// create the response
$response = $pipeline->handle($request);

// send it
$emitter->emit($response);
```

Or to send to piped example from above

```
use inroutephp\inroute\Runtime\Middleware\Pipeline;
use Laminas\Diactoros\ServerRequestFactory;
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;

(new SapiEmitter)->emit(
    (new Pipeline($router))->handle(
        (new ServerRequestFactory)->createServerRequest('GET', '/piped')
    )
);
```

Generating route paths
----------------------

[](#generating-route-paths)

```
function getUser(ServerRequestInterface $request, EnvironmentInterface $environment): ResponseInterface
{
    return new TextResponse(
        $environment->getUrlGenerator()->generateUrl('getUser', ['name' => 'myUserName'])
    );
}
```

Creating custom annotations
---------------------------

[](#creating-custom-annotations)

Inroute uses [doctrine](https://github.com/doctrine/annotations) to read annotations. Creating custom annotations is as easy as

```
namespace MyNamespace;

/**
 * @Annotation
 */
class MyAnnotation
{
    public $value;
}
```

To create annotations that automatically pipes a route through a middleware use something like the following.

```
namespace MyNamespace;

use inroutephp\inroute\Annotations\Pipe;

/**
 * @Annotation
 */
class AdminRequired extends Pipe
{
    public $middlewares = ['AuthMiddleware', 'RequireUserGroupMiddleware'];
    public $attributes = ['required_user_group' => 'admin'];
}
```

> Note that you need to supply the `AuthMiddleware` to authenticate a user and the `RequireUserGroupMiddleware` to check user priviliges for this example to function as expected. See below on how to inject a dependency container that can deliver these middlewares.

And to annotate your controller methods

```
use MyNamespace\MyAnnotation;
use MyNamespace\AdminRequired;

class MyController
{
    /**
     * @MyAnnotation(value="foobar")
     * @AdminRequired
     */
    public function aRouteThatIsOnlyOpenToAdminUsers()
    {
    }
}
```

Processing routes using compiler passes
---------------------------------------

[](#processing-routes-using-compiler-passes)

Custom annotations are most useful pared with custom compiler passes.

```
use inroutephp\inroute\Compiler\CompilerPassInterface;
use inroutephp\inroute\Runtime\RouteInterface;
use MyNamespace\MyAnnotation;

class MyCompilerPass implements CompilerPassInterface
{
    public function processRoute(RouteInterface $route): RouteInterface
    {
        if ($route->hasAnnotation(MyAnnotation::CLASS)) {
            return $route
                ->withAttribute('cool-attribute', $route->getAnnotation(MyAnnotation::CLASS)->value)
                ->withMiddleware(SomeCoolMiddleware::CLASS);
        }

        return $route;
    }
}
```

Each route has a middleware pipeline of its own. In the example above all routes annotated with `MyAnnotation` will be wrapped in `SomeCoolMiddleware`. This makes it easy to add custom behaviour to routes at compile time based on annotations.

The attribute `cool-attribute` can be accessed in middlewares using `$request->getAttribute('cool-attribute')`.

Handling dependencies with a DI container
-----------------------------------------

[](#handling-dependencies-with-a-di-container)

You may have noted that in the example above `SomeCoolMiddleware` was passed not as an instantiated object but as a class name. The actual object is created at runtime using a [PSR-11](https://www.php-fig.org/psr/psr-11/) compliant dependency injection container. The same is true for controller classes.

Create you container as part of your dispatching logic and pass it to the router using the `setContainer()` method.

```
$container = /* your custom setup */;

$router = new example\HttpRouter;

$router->setContainer($container);

// continue dispatch...
```

Dealing with routing errors
---------------------------

[](#dealing-with-routing-errors)

Route note found (http code `404`) and method not allowed (`405`) situations can be handled in one of two ways.

### Using a ResponseFactoryInterface

[](#using-a-responsefactoryinterface)

If you container contains a service `Psr\Http\Message\ResponseFactoryInterface`then that factory will be used to create and return a `404` or `405` http response.

### Catching exceptions

[](#catching-exceptions)

If no factory is defined a `inroutephp\inroute\Runtime\Exception\RouteNotFoundException`or `inroutephp\inroute\Runtime\Exception\MethodNotAllowedException` will be thrown.

###  Health Score

29

—

LowBetter than 57% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community11

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

Recently: every ~89 days

Total

12

Last Release

2381d ago

PHP version history (2 changes)1.0.0-beta1PHP ^7.1

1.0.0PHP &gt;=7.2

### Community

Maintainers

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

---

Top Contributors

[![hanneskod](https://avatars.githubusercontent.com/u/1369274?v=4)](https://github.com/hanneskod "hanneskod (41 commits)")

---

Tags

annotationsmiddlewareopenapipsr-15web-routermiddlewareopenapiannotationspsr-15web-router

### Embed Badge

![Health badge](/badges/inroutephp-inroute/health.svg)

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

###  Alternatives

[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k12](/packages/tempest-framework)[cakephp/cakephp

The CakePHP framework

8.8k19.1M1.7k](/packages/cakephp-cakephp)[thecodingmachine/graphqlite

Write your GraphQL queries in simple to write controllers (using webonyx/graphql-php).

5733.2M40](/packages/thecodingmachine-graphqlite)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[mezzio/mezzio

PSR-15 Middleware Microframework

3913.8M120](/packages/mezzio-mezzio)[mezzio/mezzio-authentication-oauth2

OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications.

28545.4k3](/packages/mezzio-mezzio-authentication-oauth2)

PHPackages © 2026

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