PHPackages                             davidecesarano/embryo-routing - 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. davidecesarano/embryo-routing

ActiveLibrary[API Development](/categories/api)

davidecesarano/embryo-routing
=============================

A PHP Router PSR compatible.

1.2.0(4y ago)41751MITPHPPHP &gt;=7.1

Since Aug 10Pushed 4y ago2 watchersCompare

[ Source](https://github.com/davidecesarano/Embryo-Routing)[ Packagist](https://packagist.org/packages/davidecesarano/embryo-routing)[ Docs](https://github.com/davidecesarano/embryo-routing)[ RSS](/packages/davidecesarano-embryo-routing/feed)WikiDiscussions master Synced today

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

Embryo Routing
==============

[](#embryo-routing)

A lightweight, fast and PSR compatible PHP Router.

Features
--------

[](#features)

- PSR (7, 11, 15) compatible.
- Static, dynamic and optional route patterns.
- Supports GET, POST, PUT, PATCH, DELETE and OPTIONS request methods.
- Supports route middlewares.
- Supports grouping routes.
- Supports resolve via Container.
- Works in subfolders.

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

[](#requirements)

- PHP &gt;= 7.1
- URL Rewriting
- A [PSR-7](https://www.php-fig.org/psr/psr-7/) http message implementation and [PSR-17](https://www.php-fig.org/psr/psr-17/) http factory implementation (ex. [Embryo-Http](https://github.com/davidecesarano/Embryo-Http))
- A [PSR-11](https://www.php-fig.org/psr/psr-11/) container implementation (ex. [Embryo-Container](https://github.com/davidecesarano/Embryo-Container))
- A [PSR-15](https://www.php-fig.org/psr/psr-15/) http server request handlers implementation (ex. [Embryo-Middleware](https://github.com/davidecesarano/Embryo-Middleware))

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

[](#installation)

Using Composer:

```
$ composer require davidecesarano/embryo-routing

```

Example
-------

[](#example)

Before defining the application routes, it is necessary to create the following objects:

- the `Container`
- the `ServerRequestFactory`
- the `ResponseFactory`
- the `RequestHandler`
- the `Emitter`

```
use Embryo\Container\Container;
use Embryo\Http\Emitter\Emitter;
use Embryo\Http\Factory\{ServerRequestFactory, ResponseFactory};
use Embryo\Http\Server\RequestHandler;
use Embryo\Routing\Router;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

$container      = new Container;
$request        = (new ServerRequestFactory)->createServerRequestFromServer();
$response       = (new ResponseFactory)->createResponse(200);
$requestHandler = new RequestHandler;
$emitter        = new Emitter;
```

Later, you can define the routes with `Router` object:

```
$router = new Router;

$router->get('/', function(Request $request, Response $response){
    $response->getBody()->write('Hello World!');
    return $response;
});
```

Now, create PSR-15 middleware queue adding required routing middlewares:

- `MethodOverrideMiddleware` for overriding the HTTP Request Method.
- `RoutingMiddleware` for match route and handler discovery.
- `RequestHandlerMiddleware` for executing request handlers discovered by router.

```
$requestHandler->add(new Embryo\Routing\Middleware\MethodOverrideMiddleware);
$requestHandler->add(new Embryo\Routing\Middleware\RoutingMiddleware($router));
$requestHandler->add(new Embryo\Routing\Middleware\RequestHandlerMiddleware($container));
$response = $requestHandler->dispatch($request, $response);
```

Finally you can produce output of the Response with `Emitter` object.

```
$emitter->emit($response);
```

Usage
-----

[](#usage)

- [Create routes](#create-routes)
- [Callbacks](#callbacks)
- [Placeholders](#placeholders)
- [Set name route](#set-name-route)
- [Create route groups](#create-route-group)
- [Add middleware to route](#add-middleware-to-route)
- [Resolve via Container](#resolve-via-container)
- [Set default namespace](#set-default-namespace)
- [Working in subfolder](#working-in-subdirectory)

### Create routes

[](#create-routes)

You can define application routes using methods on the Router object. Every method accepts two arguments:

- The route pattern (with optional placeholders)
- The route callback (a closure, a `class@method` string or a `['class', 'method']` array)

```
// GET Route
$router->get('/blog/{id}', function(Request $request, Response $response, int $id) {
    $response->getBody()->write('This is post with id '.$id);
    return $response;
});
```

Note that you can write pattern with or without "/" to first character like this: `blog/{id}`.

#### Methods

[](#methods)

Embryo Routing supports GET, POST, PUT, PATCH, DELETE and OPTIONS request methods. Every request method corresponds to a method of the Router object: `get()`, `post()`, `put()`, `patch()`, `delete()` and `options()`. You can use `all()` and `map()` methods for supporting all methods or specific route methods.

```
// All methods
$router->all('pattern', function(Request $request, Response $response) {
    //...
});

// Match methods
$router->map(['GET', 'POST'], 'pattern', function(Request $request, Response $response) {
    //...
});
```

#### Overriding the request method

[](#overriding-the-request-method)

Use `X-HTTP-Method-Override` to override the HTTP Request Method. Only works when the original Request Method is POST. Allowed values for X-HTTP-Method-Override are `PUT`, `DELETE`, or `PATCH`. Embryo uses `MethodOverrideMiddleware` for manage HTTP-Method-Override.

### Callbacks

[](#callbacks)

Each routing method accepts a callback routine as its final argument. This argument by default it accepts at least two arguments:

- **Request**. The first argument is a `Psr\Http\Message\ServerRequestInterface` object that represents the current HTTP request.
- **Response**. The second argument is a `Psr\Http\Message\ResponseInterface` object that represents the current HTTP response.
- **Placeholder(s)**. Each route placeholder as a separate argument.

#### Writing content to the response

[](#writing-content-to-the-response)

There are three ways you can write content to the HTTP response:

1. You can simply `echo()` content from the route callback: this content will be appended to the current HTTP response object.
2. You can return a `Psr\Http\Message\ResponseInterface` object.
3. You can return a `json` content when returning an array.

```
// echo
$router->get('/hello/{name}', function (Request $request, Response $response, string $name) {
    echo $name;
});

// response object
$router->get('/hello/{name}', function (Request $request, Response $response, string $name) {
    $response->getBody()->write($name);
    return $response;
});

// json
$router->get('/hello/{name}', function ($Request $request, Response $response, string $name) {
    return [
        'name' => $name
    ];
});
```

#### Closure binding

[](#closure-binding)

If you use a Closure instance as the route callback, the closure’s state is bound to the `Container` instance. This means you will have access to the DI container instance inside of the Closure via the `$this` keyword:

```
$router->get('/hello/{name}', function (Request $request, Response $response, string $name) {
    $myservice = $this->get('myservice');
    //...
});
```

#### Access to current route

[](#access-to-current-route)

If you get the route's object, you can it using the request attribute:

```
$router->get('/hello/{name}', function (Request $request, Response $response, string $name) {
    $route = $request->getAttribute('route');
    echo $route->getUri(); // /hello/name
});
```

### Placeholders

[](#placeholders)

Route patterns may use named placeholders to dynamically match HTTP request URI segments.

#### Format

[](#format)

A route pattern placeholder starts with a `{`, followed by the placeholder name, ending with a `}`. Name and value placeholder may be each character from a-z, A-Z, 0-9, including the \_ (underscore).

```
$router->get('/hello/{name}', function (Request $request, Response $response, string $name) {
    echo $name;
});
```

#### Optional

[](#optional)

To make a placeholder optional, wrap it in square brackets:

```
$router->get('/hello[/{name}]', function (Request $request, Response $response, string $name = null) {
    if ($name) {
        echo $name;
    }
    //...
});
```

You can use a multiple optional parameters:

```
$router->get('/blog[/{year}][/{month}][/{day}]', function(Request $request, Response $response, int $year = 2018, int $month = 12, int $day = 31){
    $response->getBody()->write('Blog! Year: '.$year.', Month: '.$month.', Day: '.$day);
    return $response;
});
```

For "simple slug" optional parameters, you can do this:

```
$router->get('/blog[/{year}][/{slug}]', function(Request $request, Response $response, int $year = 2018, string $slug = null){
    //...
})->where('slug', '[\/\w\-]+');
```

In this example, a URI of /`blog/2018/my-post-title` would result in the `$year` (2018) and `$slug` (my-post-title) arguments.

#### Set regex route

[](#set-regex-route)

By default the placeholders can accept any character allowed for composing an uri with the exception of the `/` character. However, placeholders can also require the HTTP request URI to match a particular regular expression. For this, you can use `where()` method:

```
$router->get('/blog/{id}/{name}', function(Request $request, Response $response, int $id, string $name){
    //...
})->where([
    'id'   => '[0-9]+',
    'name' => '[a-z]+',
]);
```

### Set name route

[](#set-name-route)

You can be assigned a name at the route with `name()` method:

```
$router->get('/hello/{name}', function (Request $request, Response $response, string $name) {
    //...
})->name('route');
```

### Create route groups

[](#create-route-groups)

You can organize routes into logical groups with `group()` method. If you want add a route prefix you can use `prefix()` method:

```
$router->prefix('/api')->group(function($router) {
    $router->get('/user/{id}', function(Request $request, Response $response, int $id) {
        //...
    });
});
```

In this example URI is, for example, /api/user/1.

### Add middleware to route

[](#add-middleware-to-route)

You can also attach a PSR-15 middleware to any route or route group. The `middleware()` method accepts a string, an array or an instance of `Psr\Http\Server\MiddlewareInterface`.

#### Route middleware

[](#route-middleware)

You can use the `middleware()` method to assign one or more middleware at the route:

```
$router->get('/users', function(Request $request, Response $response) {
    //...
})->middleware('App\TestMiddleware1', 'App\TestMiddleware2');
```

#### Group middleware

[](#group-middleware)

In addition to the routes, you can assign one or more middleware to a group and to individual routes within the group:

```
$router->prefix('/api')->middleware('App\GroupMiddlewareTest')->group(function($router) {
    $router->get('/user/{id}', function(Request $request, Response $response, int $id){
        //...
    })->middleware('App\RouteMiddlewareTest');
});
```

### Resolve via Container

[](#resolve-via-container)

In callback, in addition to closure, you can use the `class@method` string or `['className', 'methodName']` array:

```
// string
$router->get('/user/{id}', 'user@getById');

// array
use Path\To\User;

$router->get('/user/{id}', [User::class, 'geById']);
```

It translates into a class/method call like this:

```
use Embryo\Routing\Controller;
use Psr\Http\Message\ResponseInterface;

class User extends Controller
{
    public function getById(int $id): ResponseInterface
    {
        $this->response->getBody()->write('The User id is: '.$id);
        return $this->response;
    }
}
```

In this example you will have access to the DI container instance inside of the class via the `$this` keyword. If you want have access to service in container use `$this->get('myservice')`. If you want have access to the request or response instance use `$this->request` and `$this->response`. In addition, methods parameters it's may also called using `type-hinting`, which means you can put the class you need in the method and the Service Container will resolve it automatically:

```
use Path\To\MyService;
use Embryo\Routing\Controller;
use Psr\Http\Message\ResponseInterface;

class User extends Controller
{
    public function getById(MyService $service, int $id): ResponseInterface
    {
        //...
    }
}
```

### Set default namespace

[](#set-default-namespace)

You may to set default namespace for your controllers with `setNamespace()` method:

```
$router = new Router;
$router->setNamespace('App\\Controller');

$router->get('/', 'PageController@index'); // App\Controller\PageController

//...
```

### Working in subfolder

[](#working-in-subfolder)

Embryo Routing can works in a subdirectory by setting the path with `setBasePath()` method:

```
$router = new Router;
$router->setBasePath('/path/subdirectory');

$router->get('/', function(Request $request, Response $response) {
    $response->getBody()->write('Hello World!');
    return $response;
});

//...
```

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity55

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

Recently: every ~72 days

Total

9

Last Release

1788d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/16277144?v=4)[Davide Cesarano](/maintainers/davidecesarano)[@davidecesarano](https://github.com/davidecesarano)

---

Top Contributors

[![davidecesarano](https://avatars.githubusercontent.com/u/16277144?v=4)](https://github.com/davidecesarano "davidecesarano (80 commits)")

---

Tags

phppsr-7routerrouterroutingpsr router

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/davidecesarano-embryo-routing/health.svg)

```
[![Health](https://phpackages.com/badges/davidecesarano-embryo-routing/health.svg)](https://phpackages.com/packages/davidecesarano-embryo-routing)
```

###  Alternatives

[friendsofsymfony/jsrouting-bundle

A pretty nice way to expose your Symfony routing to client applications.

1.5k53.6M229](/packages/friendsofsymfony-jsrouting-bundle)[phroute/phroute

Fast, fully featured restful request router for PHP

739462.1k29](/packages/phroute-phroute)[pear2/net_routeros

This package allows you to read and write information from a RouterOS host using MikroTik's RouterOS API.

248111.7k4](/packages/pear2-net-routeros)[tobion/openapi-symfony-routing

Loads routes in Symfony based on OpenAPI/Swagger annotations

4219.5k](/packages/tobion-openapi-symfony-routing)[szenis/routing

A small and simple PHP router

162.4k2](/packages/szenis-routing)

PHPackages © 2026

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