PHPackages                             undercloud/beacon - 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. undercloud/beacon

ActiveLibrary

undercloud/beacon
=================

Beacon - PHP Routing System

1111PHP

Since Nov 22Pushed 2y ago1 watchersCompare

[ Source](https://github.com/undercloud/beacon)[ Packagist](https://packagist.org/packages/undercloud/beacon)[ RSS](/packages/undercloud-beacon/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (2)Used By (0)

Beacon - PHP Routing System
===========================

[](#beacon---php-routing-system)

[![Build Status](https://camo.githubusercontent.com/ad4b95d78480d74bd7ee6b6e5c46036bcd8cfa8ff15282756e825e2deb2ce504/68747470733a2f2f7472617669732d63692e636f6d2f756e646572636c6f75642f626561636f6e2e7376673f6272616e63683d6d6173746572)](https://travis-ci.com/undercloud/beacon)

Features
--------

[](#features)

- Zero dependency
- PCRE pattern path support
- Route groups
- Domain condition support
- HTTPS condition support
- Controller bindings
- RESTful
- Unicode
- Wildcard attributes
- Auth

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

[](#requirements)

PHP 5.4+

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

[](#installation)

`composer require undercloud/beacon`

.htaccess
---------

[](#htaccess)

Pretty URLs with .htaccess:

```
RewriteEngine On
RewriteCond   %{REQUEST_FILENAME}       !-d
RewriteCond   %{REQUEST_FILENAME}       !-f
RewriteRule   ^(.*) index.php?%{QUERY_STRING}

```

Setup
-----

[](#setup)

```
// if installed by composer
require '/path/to/vendor/autoload.php';
// if installed manually
require '/path/to/Beacon/Beacon.php';

$router = new Beacon\Router([
  // current hostname
  'host' => $_SERVER['SERVER_NAME'],
  // current http method
  'method' => $_SERVER['REQUEST_METHOD'],
  // optionaly, true if request over https
  'isSecured' => true
]);
```

Concept
-------

[](#concept)

The API is built on the principle of a [https://en.wikipedia.org/wiki/Fluent\_interface](https://en.wikipedia.org/wiki/Fluent_interface)

Define routes
-------------

[](#define-routes)

Here's a basic usage example:

```
$router
  // any of methods get,post,put or delete
  ->on('/', 'Controller::index')
  // only get method
  ->get('/user/:id', 'ControllerUser::getUser')
  // only post
  ->post('/user/:id', function () { ... })
  // fallback function
  ->otherwise(function() {
    echo 404;
  });

// resolve request
$route = $router->go($_SERVER['REQUEST_URI']);
```

`Beacon\Router::go` method return `Beacon\Route` instance with next methods:

```
// route path
$route->getPath();
// get callback
$route->getCallback();
// get binded params
$route->getParams();
// get middlewares list
$route->getMiddleware();
```

### Unicode paths

[](#unicode-paths)

Route paths can contain any Unicode character set

```
$router->on('/gâteau-français', function () { ... })
```

### Methods

[](#methods)

Complete list of avail route methods

```
/*
 * $path - request path, example /users, support PCRE
 * $call - callback, string 'Controller::action' or Closure
 * $methods - array of http methods, example ['post','put']
 */

$router->on($path, $call);
$router->get($path, $call);
$router->post($path, $call);
$router->put($path, $call);
$router->delete($path, $call);
$router->patch($path, $call);
$router->head($path, $call);
$router->match(array $methods, $path, $call);
```

### Params

[](#params)

Beacon supports named params. For example, route with binded params:

```
$router->on('/user/:id/:name(/:nickname)', 'ControllerUser::getUser');
```

from request:

```
$route = $router->go('/user/78/John');
```

will be fetched into:

```
[
  'id'       => 78,
  'name'     => 'John',
  'nickname' => null
]
```

You can also add additional check for params:

```
$router
  ->on('/user/:id/:name(/:nickname)', 'ControllerUser::getUser')
    // check numeric id
    ->withWhere('id', '/\d+/')
    // empty or invalid nickname will be replaced with 'Guest'
    ->withWhere('nickname', '/[A-Za-z0-9]+/', 'Guest')
  ->on(...);
```

Now params will be fetched into:

```
[
  'id'       => 78,
  'name'     => 'John',
  'nickname' => 'Guest'
]
```

For retrieve params use `$route->getParams()`

### Wildcard Attributes

[](#wildcard-attributes)

Sometimes it is useful to allow the trailing part of the path be anything at all. To allow arbitrary trailing path segments on a route, call the wildcard() method. This will let you specify the attribute name under which the arbitrary trailing values will be stored.

```
$router
  ->on('/foo', function() { ... })
    ->wildcard('card')
  ->on('/bar', function() { ... });

$route = $router->go('/foo/bar/baz/quux');

// ['card' => ['bar','baz','quux']]
$params = $route->getParams();
```

### Otherwise

[](#otherwise)

If request cannot be resolved, you can define fallback:

```
$router
  ->otherwise(function(){
    switch(Beacon\RouterError::getErrorCode()){
      case Beacon\RouterError::NOT_FOUND_ERROR:
      /* Same as 404 error, cannot find any path for current request */
      break;

      case Beacon\RouterError::SECURE_ERROR:
      /* Need secured connection over https */
      break;

      case Beacon\RouterError::CONTROLLER_RESOLVE_ERROR:
      /* When given method in binded contoller is unavailable */
      break;

      case Beacon\RouterError::WHERE_REGEX_ERROR:
      /* Fail parameter regex test in ->where(...) */
      break;

      case Beacon\RouterError::REST_RESOLVE_ERROR:
      /* Cannot find implemented method in given REST controller*/
      break;

      case Beacon\RouteError::AUTH_ERROR:
      /* Auth check failed */
      break;
    }
  });
```

### Controller

[](#controller)

You can define controller namespace and bind methods to path:

```
// bind path to controller
$router->controller('/users', 'ControllerUsers');
// resolve
$route = $router->go('/users/get-users');
// will return ControllerUsers::getUsers
$call = $route->getCallback();
```

If requested method undefined or is not public, Beacon return fallback function.

### Group

[](#group)

Routes can be grouped:

```
$router->group('/api', function ($router) {
  $router->get('/users', 'ControllerUsers::getUsers')
});

$route = $router->go('/api/users');
...
```

groups can be nested:

```
$router->group('/api', function ($router) {
  $router->group('/v1.1' function($router) {
    $router->get('/users', 'ControllerUsers::getUsers')
  });
});
```

### Domain

[](#domain)

If your app can de accessed from multiple hostnames, you can setup personal routes for each domains:

```
$router
  ->domain('api.example.com', function ($router) {
    $router->get('/', function () {
      echo 'api';
    });
  })
  ->get('/', function () {
    echo 'main domain';
  });
```

### REST

[](#rest)

It so easy to make RESTfull service, define path:

```
$router->resource(
  '/photo',
  'ControllerPhoto',
  // define param name, default 'id'
  $paramName' = 'photo'
);
```

and define controller with specific methods:

```
class ControllerPhoto
{
  // build list
  public function index()
  {
    ...
  }

  // build form
  public function create()
  {
    ...
  }

  // save form
  public function store()
  {
    ...
  }
  ...
}
```

Next table show conformity between request path and controller methods:

VerbPathActionCallGET/photoindexControllerPhoto::indexGET/photo/createcreateControllerPhoto::createPOST/photostoreControllerPhoto::storeGET/photo/:photoshowControllerPhoto::showGET/photo/:photo/editeditControllerPhoto::editPUT/photo/:photoupdateControllerPhoto::updateDELETE/photo/:photodestroyControllerPhoto::destroyNote, that if requested method undefined or is not public, Beacon return fallback function.Route options
-------------

[](#route-options)

All methods:

- on
- get
- post
- put
- delete
- patch
- head
- match
- controller
- group
- domain
- resource

can be additionaly setuped with next methods:

- withSecure - secure settings
- withMiddleware, withoutMiddleware, withoutAnyMiddleware - manage middleware chain
- withAuth - access checker

Options defined in parent sections, will be inherited by childs, e.g.:

```
$router
  ->group('/api', function ($router) {
    // now in inherit options defined in group
    $router->get('/users/:id', function() {...});
  })
    ->withSecure(true),
    ->withMiddleware(['MiddlewareAuth','MiddlewareCompressor'])
  ->group('/another-group', ...);
```

You can override inherited, just define personal:

```
$router->group('/api', function ($router) {
  // now in inherit options defined in group
  $router->get('/users/:id', function() {...})
    ->withSecure(false);
})
  ->withSecure(true)
  ->withMiddleware(['MiddlewareAuth','MiddlewareCompressor']);
```

For defining global pre-setuped options use `Beacon\Router::globals(array $options)`.

```
$router
  ->globals()
    withSecure(true)
    withMiddleware(['MiddlewareAuth'])
  // inherit global options
  ->get('/', 'Controller::index')
  // override global
  ->post('/users', 'ControllerUsers::getUsers')
    ->withSecure(false)
```

Middleware chain
----------------

[](#middleware-chain)

Beacon makes it easy to manage the chain of middlewares, look at this example:

```
$router
  ->globals()
    ->withMiddleware('MiddlewareAuth')
  ->on('/', function() { ... })
  ->group('/api', function ($router) {
    $router->on('/guest', 'ControllerApi::getGuests')
      withoutMiddleware('MiddlewareAuth')
      withMiddleware('MiddlewareGuest');

    $router->on('/secure')
      ->withoutAnyMiddleware()
      ->withMiddleware('MiddlewareSecure');
  })
    ->withMiddleware('MiddlewareApi');
```

Now middleware stack for:

- `/` is `['MiddlewareAuth','MiddlewareApi']`
- `/api/guest` is `['MiddlewareApi','MiddlewareGuest']`
- `/api/secure` is `['MiddlewareSecure']`

Secure
------

[](#secure)

If you wanna routes, that must be handle over https only, setup it like this:

```
$router
  ->get('/pay', 'System::pay')
    ->withSecure(true)
```

Auth
----

[](#auth)

You can assign callback for access check:

```
$router
  ->get('/dashboard', 'System::dashboard')
  ->withAuth('User::isAdmin')
```

Or for high level methods `group`, `domain`, `controller`, `rest`:

```
$router
  ->group('/api', function(){
    ...
    })
      ->withAuth('Api::checkKey')
```

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

[](#error-handling)

see [Otherwise section](https://github.com/undercloud/beacon#otherwise)

###  Health Score

22

—

LowBetter than 25% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity8

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity43

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/920a45a1bd1af5960cf6781cd2d8831ebfe2890c1077210667802afa109d8d13?d=identicon)[undercloud](/maintainers/undercloud)

---

Top Contributors

[![undercloud](https://avatars.githubusercontent.com/u/9054259?v=4)](https://github.com/undercloud "undercloud (24 commits)")

---

Tags

managemiddlewarerouteroutingurl

### Embed Badge

![Health badge](/badges/undercloud-beacon/health.svg)

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

PHPackages © 2026

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