PHPackages                             mcustiel/power-route - 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. mcustiel/power-route

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

mcustiel/power-route
====================

Power Route is a configurable router for PHP

v3.0.1(7y ago)7549.6k↓40.4%11GPL-3.0+PHPPHP &gt;=5.6

Since Oct 21Pushed 7y ago1 watchersCompare

[ Source](https://github.com/mcustiel/PowerRoute)[ Packagist](https://packagist.org/packages/mcustiel/power-route)[ RSS](/packages/mcustiel-power-route/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (7)Dependencies (4)Versions (13)Used By (1)

PowerRoute! is a PHP routing system that can execute different sets of actions based in several components of the HTTP requests and is fully compatible with PSR-7.

The configuration is formed by three main components and defines a binary tree:

- **Input sources**: The input sources are the component that takes data from the request to be evaluated.
- **Matchers**: This component receives the value from the input source and executes a check on it.
- **Actions**: The component that is executed based in the result of the check executed by matchers.

In the configuration the actions can be set for the case in which the matcher returns true and for the case in which it returns true, hence building a binary tree.

The full system can be extended by adding input sources, matchers and actions. Also the names used in the configuration to identify the components can be assigned arbitrarily.

The components are grouped forming the nodes of the binary tree, each node looks as following:

```
'expectationUrl' => [
    'condition' => [
        'one-of' => [
            [
                'input-source' => ['url' => 'path'],
                'matcher' => [ 'matches' => '/some/url/?' ],
            ],
        ],
    ],
    'actions' => [
        'if-matches' => [
            ['myCustomAction' => 'withSomeParameter'],
        ],
        'else' => [
            ['notFound' => null],
        ],
    ],
],
```

[![Build Status](https://camo.githubusercontent.com/6905f01293c4cc43ebf56f424e2eea835b53b3609eb58aca195ff1dc2c329cb0/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d6375737469656c2f506f776572526f7574652f6261646765732f6275696c642e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mcustiel/PowerRoute/build-status/master)[![Code Coverage](https://camo.githubusercontent.com/0fb9258ed416e1dec2bef71c3ccb65355a3ab1c851f6e090c044dc6551528a25/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d6375737469656c2f506f776572526f7574652f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mcustiel/PowerRoute/?branch=master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/f74143038f51419254d87491ceca64e3c596ff585f1cda413e42208745e585eb/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d6375737469656c2f506f776572526f7574652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mcustiel/PowerRoute/?branch=master)[![PPM Compatible](https://raw.githubusercontent.com/php-pm/ppm-badge/master/ppm-badge.png)](https://github.com/php-pm/php-pm)

[![SensioLabsInsight](https://camo.githubusercontent.com/22c561015d978339daf089790f73d076f4cc65f9193fdebced39e34b90a23ddf/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f66323865636464312d323864302d343338352d393138332d3937326361353563666539332f6269672e706e67)](https://insight.sensiolabs.com/projects/f28ecdd1-28d0-4385-9183-972ca55cfe93)

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

[](#table-of-contents)

- [Installation](#installation)
- [How to use](#how-to-use)
    - [The configuration](#the-configuration)
    - [The code](#the-code)
- [Predefined components](#predefined-components)
    - [Input sources](#input-sources)
    - [Matchers](#matchers)
    - [Actions](#actions)
- [Extending PowerRoute!](#extending-powerroute)
    - [Creating your own actions](#creating-your-own-actions)
        - [Using PSR-7 middleware](#using-psr7-middleware)
        - [TransactionData class](#transactiondata-class)
        - [Placeholders](#placeholders)
    - [Creating your own input sources](#creating-your-own-input-sources)
    - [Creating your own matchers](#creating-your-own-matchers)

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

[](#installation)

This project is published in packagist, so you just need to add it as a dependency in your composer.json:

```
    "require": {
        // ...
        "mcustiel/power-route": "*"
    }
```

How to use
----------

[](#how-to-use)

### The configuration

[](#the-configuration)

The configuration must be a php array. It must define two keys:

- root: The name of the root node of the graph.
- nodes: The definition of all the nodes, this is a key =&gt; value pairs array where key is the name of the node and value it's definition.

#### Example

[](#example)

A configuration that always redirects to google.com:

```
[
    'root' => 'default',
    'nodes' => [
        'default' => [
            'condition' => [],
            'actions' => [
                'if-matches' => [
                    [ 'redirect' => 'http://www.google.com' ]
                ]
            ]
        ]
    ]
]
```

You can use the names you prefer for the input sources, the matchers and the actions and then map them in the factories provided by this library.

### The code

[](#the-code)

After all the configuration is correctly defined, Executor class must be used to walk the graph based in the request received. To create an instance of Executor class, the factories for Actions, Input Sources and Matchers must be created first. Each factory constructor expects an array of Mcustiel\\Creature\\CreatorInterface objects, indexed by the identificator of the class used in PowerRoute! config file. See following example:

```
use Mcustiel\PowerRoute\PowerRoute;

use Mcustiel\PowerRoute\Common\Factories\ActionFactory;
use Mcustiel\PowerRoute\Common\Factories\InputSourceFactory;
use Mcustiel\PowerRoute\Common\Factories\MatcherFactory;
use Mcustiel\PowerRoute\Common\Factories\ActionFactory;

Mcustiel\PowerRoute\Common\Conditions\ConditionsMatcherFactory;

use Mcustiel\PowerRoute\Matchers\NotNull;
use Mcustiel\PowerRoute\Matchers\Equals;

use Mcustiel\PowerRoute\InputSources\QueryStringParam;

use Mcustiel\PowerRoute\Actions\Redirect;

use Mcustiel\Creature\SingletonLazyCreator;

use Your\Namespace\MyMatcher;
use Your\Namespace\MyInputSource;
use Your\Namespace\MyAction;

$matcherFactory = new MatcherFactory(
    [
        'notNull' => new SingletonLazyCreator(NotNull::class),
        'equals' => new SingletonLazyCreator(Equals::class),
        'someSpecialMatcher' => new SingletonLazyCreator(MyMatcher::class)
    ]
);
$inputSourceFactory = new InputSourceFactory(
    [
        'get' => new SingletonLazyCreator(QueryStringParam::class),
        'someSpecialInputSource' => new SingletonLazyCreator(MyInputSource::class)
    ]
);
$actionFactory = new ActionFactory(
    [
        'redirect' => new SingletonLazyCreator(Redirect::class),
        'someSpecialAction' => new SingletonLazyCreator(MyAction::class)
    ]
);

$config = $yourConfigManager->getYourPowerRouteConfig();
$router = new PowerRoute(
    $config,
    $actionFactory,
    ConditionsMatcherFactory($inputSourceFactory, $matcherFactory)
);
```

After you have your executor instance, just call start method with the PSR7 request and response:

```
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response\SapiEmitter;

$request = ServerRequestFactory::fromGlobals();
$response = $router->start($request, new Response());

(new SapiEmiter())->emit($response);
```

Or, to boost it up, you can use [PHP-PM](https://github.com/php-pm):

```
namespace Your\Namespace;

class MyApplication
{
    private $router;

    public function __construct()
    {
        // Set up the application
        // ...
        $this->router = new PowerRoute(
            $config,
            $actionFactory,
            ConditionsMatcherFactory($inputSourceFactory, $matcherFactory)
        );
    }

    public function __invoke($request, $response, $next = null)
    {
        return $this->router->start($request, $response);
    }
}
```

and run it as:

```
vendor/bin/ppm start --bridge=PHPPM\\Psr7\\Psr7Bridge --bootstrap=Your\\Namespace\\MyApplication
```

Predefined components
---------------------

[](#predefined-components)

### Input sources

[](#input-sources)

#### Cookie

[](#cookie)

Allows to match the request body.

#### Cookie

[](#cookie-1)

Allows to execute actions based in cookies from the http request.

##### Arguments

[](#arguments)

The name of the cookie.

#### Header

[](#header)

Allows to execute actions based in headers from the http request.

##### Arguments

[](#arguments-1)

The name of the header.

#### Method

[](#method)

Returns the http method used to execute request. It receives no parameters.

#### QueryStringParam

[](#querystringparam)

Allows to execute actions based in parameters from the request's query string.

##### Arguments

[](#arguments-2)

The name of the query string parameter.

#### Url

[](#url)

Allows to execute actions based in the url or parts of it.

##### Arguments

[](#arguments-3)

A string specifying the part of the url to evaluate. With the following possible values:

- **full**: Evaluates the full url.
- **host**: Evaluates the host.
- **scheme**: Evaluates the scheme.
- **authority**: Evaluates the authority part.
- **fragment**: Evaluates the fragment.
- **path**: Evaluates the path.
- **port**: Evaluates the port.
- **query**: Evaluates the query.
- **user-info**: Evaluates the user information part.

### Matchers

[](#matchers)

#### CaseInsensitiveEquals

[](#caseinsensitiveequals)

Useful to compare two strings without taking case into account.

#### Contains

[](#contains)

This matcher returns true if the value from the input source contains as a substring the value received as an argument.

#### Equals

[](#equals)

Returns true if the value from the input source is equal to another value received as argument.

#### InArray

[](#inarray)

Returns true if the value from the input source is in a list of values received as argument.

#### NotEmpty

[](#notempty)

Returns true if the value from the input source is not empty.

#### NotNull

[](#notnull)

Returns true if the value from the input source is not null.

#### RegExp

[](#regexp)

Returns true if the value from the input source matches a regular expression received as argument.

### Actions

[](#actions)

### Goto

[](#goto)

This is a default action that is always added, it's identifier is the string 'goto'. It allow to jump the execution to another node. It's argument is the name of the node to execute.

#### DisplayFile

[](#displayfile)

This action displays a file. Its path must be defined as argument.

#### NotFound

[](#notfound)

This action sets the http status code to 404 in the response.

#### Redirect

[](#redirect)

This action adds a Location header to the response and set the http status code to 302. Its redirection target must be defined as argument.

#### SaveCookie

[](#savecookie)

This action sets the value of a cookie. It receives as an argument an object with all the needed data for the cookie:

- name
- value
- domain
- path
- secure

#### ServerError

[](#servererror)

Sets the response statusCode to 500. Other error statusCode can also be passed as argument. On invalid error given, sets 500.

#### SetHeader

[](#setheader)

This action sets the value of a header. As an argument receives an object with the following keys:

- name
- value

#### StatusCode

[](#statuscode)

Sets the response statusCode to 200 as default. Other error statusCode can be passed as argument. On invalid error throws an exception.

Extending PowerRoute!
---------------------

[](#extending-powerroute)

### Creating your own actions

[](#creating-your-own-actions)

To create your own actions to be used through PowerRoute! you have to create a class implementing ActionInterface. If you want to give your action the ability to support placeholders, you you must use PlacheolderEvaluator trait.

- **ActionInterface** defines the method that should be implemented by the action.
- **PlaceholderEvaluator** defines the method getValueOrPlaceholder, that gives your action the ability to parse possible placeholders in a string.

```
interface ActionInterface
{
    public function execute(\Mcustiel\PowerRoute\Common\TransactionData $transactionData, $argument = null);
}
```

TransactionData is an object that is passed as an argument to all actions, it is used to share the request, the response and other data that you may want to share between them.

Inside an action you should retrieve the object you want to modify from TransactionData (request or response object). Then you modify it and set the new object again in TransactionData. This must be done this way because PSR7 are immutable.

You can even init a framework inside an action.

#### Using PSR7 middleware:

[](#using-psr7-middleware)

PowerRoute! supports psr-7 middlewares as actions. All you need to do is to map the action name in the config to a class implementing the following method:

```
function __invoke($request, $response, $next = null);
```

You can also map the action name to a callable with that signature.

PowerRoute! will call the middleware and pass the configured argument as the `$next` argument.

##### Example:

[](#example-1)

For the action config:

```
    [ 'myMiddleware' => new OtherMiddleware() ]
```

And the factory setup:

```
    [
        'myMiddleware' => new LazyCreator(MyMiddlewareImplementation::class)
    ]
```

PowerRoute will do something like this:

```
    $implementation = new MyMiddleWareImplementation();
    $implementation($request, $response, new OtherMiddleware());
```

#### Examples of an action:

[](#examples-of-an-action)

```
interface ActionInterface
{
    /**
     * @param \Mcustiel\PowerRoute\Common\TransactionData $transactionData This object is modified inside the class.
     * @param mixed                                       $argument        This optional argument comes from the config of PowerRoute!
     */
    public function execute(TransactionData $transactionData, $argument = null);
}
```

```
class Redirect implements ActionInterface
{
    use PlaceholderEvaluator;

    public function execute(TransactionData $transactionData, $argument = null)
    {
        return $transactionData->setResponse(
            $transactionData->getResponse()
            ->withHeader(
                'Location',
                $this->getValueOrPlaceholder($argument, $transactionData)
            )
            ->withStatus(302)
        );
    }
}
```

#### TransactionData class:

[](#transactiondata-class)

This class is passed as an argument to every action and defines two methods to access the current request and the corresponding response (getRequest and getResponse respectively). Also it gives you the ability to save and fetc custom variables throught **get($name)** and **set($name, $value)** methods.

#### Placeholders:

[](#placeholders)

The arguments an action receives can include a placeholder to access values from the TransactionData object. The arguments have the following format:

```
{{source.name}}

```

Where source indicates from where to obtain the value, and name is the identifier associated with the given value.

#### Possible placeholder sources:

[](#possible-placeholder-sources)

- **var**: allows you to access some custom value saved in the TransactionData object.
- **uri**: allows you to access data from the url used to request. If you call it without an identifier, it returns the full url. If not, it allows a serie of identifiers to retrieve parts of the request:
    - **full**: also returns the full url.
    - **host**: returns the host part of the url.
    - **scheme**: returns the scheme part of the url.
    - **authority**: returns the authority part of the url.
    - **fragment**: return the fragment part of the url.
    - **path**: returns the path of the url used in the current request.
    - **port**: returns the port requested in the url.
    - **query**: returns the query string from the current request.
    - **user-info**: returns the user information specified in the url.
- **method**: returns the method used in the current request.
- **get**: allows you to access a parameter from the query string, it must be specified as the name part of the placeholder.
- **header**: allows you to access a header, it must be specified as the name part of the placeholder.
- **cookie**: allows you to access a cookie, it must be specified as the name part of the placeholder.
- **post**: allows you to access a post variable, it must be specified as the name part of the placeholder.
- **bodyParam**: allows you to access a variable from the body, it must be specified as the name part of the placeholder.

\*\* **Note**: See PSR7 documentation for more information about previous sources.

### Creating your own input sources

[](#creating-your-own-input-sources)

The input source is the component used to access data from the request, it uses a matcher uses to validate the data and the request.

It also should extend AbstractArgumentAware to have access to the argument from the configuration and it must implement InputSourceInterface. It must return the value so PowerRoute! gives it to the matcher.

```
interface InputSourceInterface
{
    /**
     * @param \Psr\Http\Message\ServerRequestInterface $request
     * @param mixed                                    $argument
     *
     * @return mixed
     */
    public function getValue(ServerRequestInterface $request, $argument = null);
}
```

#### Example of an InputSource:

[](#example-of-an-inputsource)

```
class Header implements InputSourceInterface
{
    public function getValue(ServerRequestInterface $request, $argument = null)
    {
        $header = $request->getHeaderLine($argument);
        return $header ?: null;
    }
}
```

### Creating your own matchers

[](#creating-your-own-matchers)

The matcher is the component in charge of executing a check against the value obtained from the request by the InputSource. To create your own matcher, you must create a class that should extend AbstractArgumentAware to access the argument and must implement MatcherInterface.

```
interface MatcherInterface
{
    /**
     * @param mixed $value
     * @param mixed $argument
     *
     * @return boolean
     */
    public function match($value, $argument = null);
}
```

#### Example of a Matcher:

[](#example-of-a-matcher)

```
class Equals implements MatcherInterface
{
    public function match($value, $argument = null)
    {
        return $value == $argument;
    }
}
```

Examples
--------

[](#examples)

Phiremock uses PowerRoute, you can check it's config file [here](https://github.com/mcustiel/phiremock/blob/master/src/Server/Config/router-config.php).

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity39

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 98.7% 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 ~171 days

Recently: every ~253 days

Total

8

Last Release

2660d ago

Major Versions

v0.5 → v1.0.02015-11-11

v1.0.0 → v2.0.02016-02-25

v2.x-dev → v3.0.02017-04-15

PHP version history (2 changes)v0.5PHP &gt;=5.5

v3.0.0PHP &gt;=5.6

### Community

Maintainers

![](https://www.gravatar.com/avatar/8d9b3ff93206038debfa1f16a11bbfc10fca9b2f4ddfdafa00e27365d290cf0d?d=identicon)[mcustiel](/maintainers/mcustiel)

---

Top Contributors

[![mcustiel](https://avatars.githubusercontent.com/u/3268370?v=4)](https://github.com/mcustiel "mcustiel (76 commits)")[![marcuswinkler](https://avatars.githubusercontent.com/u/5886824?v=4)](https://github.com/marcuswinkler "marcuswinkler (1 commits)")

---

Tags

binary-treeextendablepsr-7routerroutingrouterextensibleconfigurable

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mcustiel-power-route/health.svg)

```
[![Health](https://phpackages.com/badges/mcustiel-power-route/health.svg)](https://phpackages.com/packages/mcustiel-power-route)
```

###  Alternatives

[symfony/routing

Maps an HTTP request to a set of configuration variables

7.6k789.4M1.8k](/packages/symfony-routing)[nikic/fast-route

Fast request router for PHP

5.3k92.4M668](/packages/nikic-fast-route)[altorouter/altorouter

A lightning fast router for PHP

1.3k3.4M68](/packages/altorouter-altorouter)[league/route

Fast routing and dispatch component including PSR-15 middleware, built on top of FastRoute.

6633.1M115](/packages/league-route)[aura/router

Powerful, flexible web routing for PSR-7 requests.

5231.5M67](/packages/aura-router)[coffeecode/router

A classic CoffeeCode Router is easy, fast and extremely uncomplicated. Create and manage your routes in minutes!

181111.1k5](/packages/coffeecode-router)

PHPackages © 2026

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