PHPackages                             aurasidera/sextant - 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. aurasidera/sextant

ActiveLibrary[Framework](/categories/framework)

aurasidera/sextant
==================

Flexible and unopinionated PHP routing library.

v3.3(3y ago)0261GPL-3.0-or-laterPHPPHP &gt;=7.0.0

Since Mar 20Pushed 3y ago1 watchersCompare

[ Source](https://github.com/AuraSidera/Sextant)[ Packagist](https://packagist.org/packages/aurasidera/sextant)[ RSS](/packages/aurasidera-sextant/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (9)Dependencies (1)Versions (10)Used By (0)

Sextant
=======

[](#sextant)

Flexible and unopinionated PHP routing library.

Sextant allows to easily define routes without forcing users to adhere any specific convention, nor implementing over-complicated patterns. You declare a list of [routes](#routes) as a pair ([condition](#conditions), [action](#actions)): action of first route whose condition is satisfied will be performed.

A [condition](#conditions) is anything *callable* which can return a boolean value. A bunch of ready-to-use condition models are available for you by default, but you will probably end up using the almighty *Simple* condition, which natively supports method and URL matching, and named parameters in URL.

An [action](#conditions) is anything *callable*. Really, nothing fancy here. Sextant has ready-to-use action models already available, such as "show this string", "shows this JSON", "include this PHP script", etc..

You can define a default action to perform when no route matches (useful for custom 404 pages).

Installation
============

[](#installation)

Sextant can be installed through [Composer](https://getcomposer.org/), although manual installation is available as well.

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

[](#requirements)

```
php>= 7.0.0

```

Composer
--------

[](#composer)

Add `aura/sextant` to your `composer.json` file, or run:

```
composer require aura/sextant

```

Manual
------

[](#manual)

Clone or download this repository:

```
git clone https://github.com/AuraSidera/Sextant.git
```

or

```
wget https://github.com/AuraSidera/Sextant/archive/master.zip
```

File structure adheres to PSR-4: no big surprises when including files.

Examples
========

[](#examples)

Basic usage: covers most use cases!
-----------------------------------

[](#basic-usage-covers-most-use-cases)

For most applications you will just need some mechanism to associate actions to URLs. That's great, and couldn't be simpler! You can just copy-paste this and ask no questions:

```
// Initializes just a couple of stuffs
$router = new \AuraSidera\Sextant\Router();
$router->setConditionFactory(new \AuraSidera\Sextant\ConditionFactory\Simple())
       ->setActionFactory(new \AuraSidera\Sextant\ActionFactory\Script());

// Declares routes
$router->addRoute(['GET', '/'], 'homepage.php')
       ->addRoute(['GET', 'users/{id}'], 'user.php')
       ->addRoute(['GET', 'users/{id}/activities/{from:date}/{to:date}'], 'user_activities.php')
       ->setDefaultAction(new \AuraSidera\Sextant\ActionFactory\NotFound());

// Reads request state
$state = \AuraSidera\Sextant\State::getStateFromServer();

// Gets the job done!
$router->match()
```

What's going on here?

- First we need to initialize the router. Obviously.
- Then we set default abstract factories for conditions and actions. Not necessary, but makes things much easier!
- We declare routes!
    - We set the `ConditionFactory\Simple` as default factory for conditions, so we can just write them as arrays `[method, URL pattern]`. And it will bind values to placeholders in brackets, like `{id}` too! Also, you can require values to be of a specific type, like `{from:date}`
    - We set the `ActionFactory\Script` as default factory for actions, so we can just write the name of a PHP file at it will be executed; GET/POST parameters, headers, named parameters from URL will be passed to the action, so no worries
- We set a default action, using Sextant's built-in `ActionFactory\NotFound` factory
- We tell the router to proceed and find a matching route That's all, really.

Advanced usage
--------------

[](#advanced-usage)

To get the most out of Sextant you need some knowledge about the system. Be sure to read (and understand) the [Concepts](#concepts) section before proceeding.

Using default factories is cool, but sometimes you just need more flexibility. That's fine: you can still set default factories, but override them with specific ones for some routers. Suppose you are fine with the behavior of the `ConditionFactory\Simple` most of the time, but you want an action to be performed for a specific URL pattern regardless of condition: you can use the basic usage example and add:

```
$url_pattern_condition = new \AuraSidera\ConditionFactory\UrlPattern();
...
$router->addRoute($url_pattern_condition('respond-to-any-method'), 'script.php');
```

And it goes similar for actions, suppose you want to show a JSON document:

```
$json_action = new \AuraSidera\ActionFactory\Json();
...
$router->addRoute(['GET', 'my-json'], $json_action('path-to-json.json'));
```

Guess what? You can mix conditions and actions:

```
$url_pattern_condition = new \AuraSidera\ConditionFactory\UrlPattern();
$json_action = new \AuraSidera\ActionFactory\Json();
...
$router->addRoute($url_pattern_condition('respond-to-any-method'), $json_action('path-to-json.json'));
```

This becomes more verbose: that's the trade-off between being concise and being flexible.

Sextant provides some ready-to-use condition and action factories you can play around with. If you want to go even further, you can play around with *meta conditions*: they are special conditions which allows to build arbitrarily complex, boolean-based conditions. Take this purposely over-complicated condition:

```
$method = new \AuraSidera\ConditionFactory\Method();
$url = new \AuraSidera\ConditionFactory\UrlPattern();
$and = new \AuraSidera\ConditionFactory\Conjunction();
$or = new \AuraSidera\ConditionFactory\Disjunction();
$not = new \AuraSidera\ConditionFactory\Negation();
...
$route->addRoute(
    $and(
        $or($not($method('GET')), $url('users/{id}')),
        $or($method('GET'), $url('users'), $url('users/{id}/edit')),
        $not($method('POST'))
    ),
    'some-action.php'
);
```

What is this mess? That's a route which requires:

```
(method != GET OR URL = users/{id}) AND (method = GET OR URL = users OR url = users/{id}/edit) AND (method != POST)

```

clearly that's not a realistic route, but you can see how any formula in [Conjunctive Normal Form](https://en.wikipedia.org/wiki/Conjunctive_normal_form) can be expressed by these mechanism. Sextant is therefore *complete* with respect to boolean algebra! Hurray!

TLDR: You can create custom complex boolean conditions on the fly without touching the code.

Nerd usage
----------

[](#nerd-usage)

Why should you? I see, you are *that* type of person...

You can define your own conditions and actions. Bear in my the following mantra:

```
condition: State => bool
action: State => nothing

```

When implementing custom actions or conditions, match those types and you will be fine. You can use functions, anonymous functions, closure or callable objects (implementing the `__invoke` magic method). Here's an example:

```
$router->addRoute(
    function (\AuraSidera\Sextant\State $state) {
        if ($state->getUrl() == 'X') {
            $state->addMatch('X') = 42;
            return true;
        }
        else {
            return count($state->getParametersAsDictionary()) < count($state->getHeadersAsDictionary());
        }
    },
    function (\AuraSidera\Sextant\Sate $state) {
        echo "This is the URL: " . $state->getUrl() . "";
        echo "And these are the matches I got: ";
        print_r($state->getMatchesAsDictionary());
    }
);
```

Pretty neat, isn't it?

Concepts
========

[](#concepts)

Main concepts in Sextant.

State
-----

[](#state)

A state is an object representing current state of the request. State always includes:

- URL
- method
- request parameters (GET, POST, ...) as associative array
- HTTP headers as associative array
- matches, an associative array filled with URL matching information (with any)

all of which can be retrieved using the appropriate getter method. A state can be automatically read from server by using the helper static factory method `getStateFromServer`:

```
$state = \AuraSidera\Sextant\State::getStateFromServer();
$url = $state->getUrl();
$method = $state->getMethod();
$parameters = $state->getParametersAsDictionary();
$headers = $state->getHeadersAsDictionary();
$matches = $state->getMatchesAsDictionary();
```

State can be decorated with named entities, which can be accessed both with member and array access syntax. Trying to read an undefined entity will return `null`:

```
$state = \AuraSidera\Sextant\State::getStateFromServer();
$state->some_name = 42;
echo $state->some_name;  // Displays 42

echo isset($state->fake) ? 'set' : 'unset';  // Displays 'unset'
echo $state->fake;  // Displays '' (a null value is print)

$state['other_name'] = 21;  // Array access works too, both for writing...
echo $state['other_name'];  // ... and reading values
echo $state->other_name;    // It is fine to mix both styles
```

Conditions
----------

[](#conditions)

A condition is any *callable* which returns a boolean. Sextant will automatically pass a State testing a route. Sextant also offers a number of ready-to-use condition in the form of abstract factories, under the `ConditionFactory` namespace. Factories can be instantiated and used in routes as in the following example:

```
// Instantiates a condition factory which produces conditions matching methods
$method_factory = new \AuraSidera\ConditionFactory\Method();

// Matches only HTTP/GET requests
$method_condition_get = $method_factory('GET');

// Matches only HTTP/POST requests
$method_condition_post = $method_factory('POST');

// Conditions can be used in routes
$router->addRoute($method_condition_get, 'action_1');
$router->addRoute($method_condition_post, 'action_2');
```

It is usually more convenient to use the following, equivalent, more concise and clearer syntax:

```
$method = new \AuraSidera\ConditionFactory\Method();

$router->addRoute($method('GET'), 'action_1');
$router->addRoute($method('POST'), 'action_2');
```

Note that, although Sextant uses classes to implement factories which produce conditions, this pattern is not mandatory. It is possible to use any type of function (including anonymous functions, closures and callable objects):

```
function my_condition(\AuraSidera\Sextant\State $state): bool {
    return true;
}

$router->addRoute('my_condition', 'action');
```

Actions
-------

[](#actions)

Actions are *callable*, without other particular requirements. They usually produce some type of output in the page, set some headers, manipulate a database, or a mix of those. Sextant will automatically inject the state when calling an action. Sextant has a number of ready-to-use actions, such as a default 404 page setting the appropriate header, a JSON renderer, a file rendered and a script executor. The `ActionFactory` contains such action factories. An action factory is an object building an action, which can be later used in a route:

```
// Istantiates an action factory rendering a JSON document
$json_action_factory = new \AuraSidera\ActionFactory\Json();

// Renders a JSON when called
$json_action = $json_action_factory('path-to-document.json');

// Actions can be used in routes
$router->addRoute('condition', $json_action);
```

The following equivalent and more concise syntax is preferred:

```
$json = new \AuraSidera\ActionFactory\Json();

$router->addRoute('condition', $json('path-to-document.json'));
```

Sextant used classed to implement factories which produce actions, but this is not mandatory. Custom functions can be used as well:

```
function my_action(\AuraSidera\Sextant\State $state) {
    echo "Hello, world!";
    $state->track = 1;
}
```

Actions are allowed to change named entities associated to `$state`, but cannot modify URL, methods, parameters or headers.

Routes
------

[](#routes)

A route is an association between a condition and an action. Routes are declared inside a router, which will eventually try to match them in a given context (URL, method, headers, etc.). First route whose condition is satisfied in the context will be chosen, and its action performed. Routes are tested in the same order they are declared.

###  Health Score

26

—

LowBetter than 41% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity57

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

Every ~135 days

Recently: every ~179 days

Total

9

Last Release

1202d ago

Major Versions

v1.1 → v2.02020-09-07

v2.2 → v3.02021-07-16

### Community

Maintainers

![](https://www.gravatar.com/avatar/bdf0331e590362eaf3a717eb9d4a83ad93599ceff80527fff014eb998a9f17a8?d=identicon)[marco-zanella](/maintainers/marco-zanella)

---

Top Contributors

[![marco-zanella](https://avatars.githubusercontent.com/u/9591069?v=4)](https://github.com/marco-zanella "marco-zanella (22 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/aurasidera-sextant/health.svg)

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

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k104.3M829](/packages/laravel-socialite)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k38.6M289](/packages/laravel-dusk)[pinguo/php-msf

Pinguo Micro Service Framework For PHP

1.7k4.2k](/packages/pinguo-php-msf)[nineinchnick/edatatables

Grid widget for the Yii Framework, wrapper for the DataTables jQuery plugin

173.2k](/packages/nineinchnick-edatatables)[link-cloud/fast-hyperf

LinkCloud Fast Hyperf

241.2k1](/packages/link-cloud-fast-hyperf)

PHPackages © 2026

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