greg-md/php-router

A powerful routing for PHP.

dev-master 2019-07-23 22:12 UTC

This package is auto-updated.

Last update: 2024-12-24 10:10:52 UTC


README

StyleCI Build Status Total Downloads Latest Stable Version Latest Unstable Version License

A powerful routing for PHP.

Table of Contents:

Requirements

  • PHP Version ^7.1

How It Works

First of all, you have to initialize a Router:

$router = new \Greg\Routing\Router();

Then, set up some routes:

$router->any('/', function() {
    return 'Hello World!';
}, 'home');

$router->get('/page/{page}.html', function($page) {
    return "Hello on page {$page}!";
}, 'page');

$router->post('/user/{id#uint}', 'UsersController@save', 'user.save');

If you set an action like Controller@action, when dispatching it will instantiate the UsersController and call the save public method.

Now, you can dispatch URLs path:

echo $router->dispatch('/'); // result: Hello World!

// Initialize "UsersController" and execute "save" method.
echo $router->dispatch('/user/1', 'POST');

and, get URLs for them:

$router->url('home'); // result: /

$router->url('home', ['foo' => 'bar']); // result: /?foo=bar

$router->url('user.save', ['id' => 1]); // result: /user/id

$router->url('user.save', ['id' => 1, 'debug' => true]); // result: /user/id?debug=true

Optionally, you can add a dispatcher to manage actions.

Let say you want to add the Action suffix to action names:

$router->setDispatcher(function ($action) {
    if (is_callable($action)) {
        return $action;
    }

    return $action . 'Action';
});

Also, you can inverse the control of the controllers.

Let say you want instantiate the controller with some custom data, or use some external IoC interface and run the init method if exists.

$router->setIoc(function ($controllerName) {
    // Let say you already have an IoC container.
    global $iocContainer;

    $controller = $iocContainer->load($controllerName);

    if (method_exists($controller, 'init')) {
        $controller->init();
    }

    return $controller;
});

Routing Schema

Routing schema supports parameters and optional segments.

Parameter format is {<name>[:<default>][#<type>][|<regex>]}?.

<name> - Parameter name;
<default> - Default value;
<type> - Parameter type. Supports int, uint, boolean(or bool);
<regex> - Parameter regex;
? - Question mark from the end determine if the parameter should be optional.

Only <name> is required in the parameter.

Optional segment format is [<schema>]. Is working recursively.

<schema> - Any routing schema.

It is very useful when you want to use the same action with different routing schema.

Example

Let say we have a page with all articles of the same type, including pagination. The route for this page will be:

$router->get('/articles/{type:lifestyle|[a-z0-9-]+}[/page-{page:1#uint}]', 'ArticlesController@type', 'articles.type');

type parameter is required in the route. Default value is lifestyle and should consist of letters, numbers and dashes.

page parameter is required in its segment, but the segment entirely is optional. Default value is 1 and should consist of unsigned integers. If the parameter will not be set or will be the same as default value, the entire segment will be excluded from the URL path.

echo $router->url('articles.type'); // result: /articles/lifestyle

echo $router->url('articles.type', ['type' => 'travel']); // result: /articles/travel

echo $router->url('articles.type', ['type' => 'travel', 'page' => 1]); // result: /articles/travel

echo $router->url('articles.type', ['type' => 'travel', 'page' => 2]); // result: /articles/travel/page-2

As you can see, there are no more URLs where you can get duplicated content, which is best for SEO. In this way, you can easily create good user friendly URLs.

Router

Below you can find a list of supported methods.

  • url - Fetch an URL of a route;
  • dispatch - Dispatch an URL path;
  • any - Create a route for any request method;
  • request - Create a route for a specific request method;
    • get - Create a GET route;
    • head - Create a HEAD route;
    • post - Create a POST route;
    • put - Create a PUT route;
    • delete - Create a DELETE route;
    • connect - Create a CONNECT route;
    • options - Create a OPTIONS route;
    • trace - Create a TRACE route;
    • patch - Create a PATCH route;
  • hidden - Create a hidden route. You can not dispatch it, but you can generate URLs from it;
  • group - Create a group of routes;
  • find - Find a route by name;
  • bind - Set an input/output binder for a parameter;
  • bindStrategy - Set an input/output binder for a parameter, using strategy;
  • bindIn - Set an input binder for a parameter;
  • bindInStrategy - Set an input binder for a parameter, using strategy;
  • binderIn - Get the input binder of a parameter;
  • bindInParam - Bind an input parameter;
  • bindOut - Set an output binder for a parameter;
  • bindOutStrategy - Set an output binder for a parameter, using strategy;
  • binderOut - Get the output binder of a parameter;
  • bindOutParam - Bind an output parameter;
  • pattern - Set a parameter pattern;
  • type - Set a parameter type;
  • getPattern - Get a parameter pattern;
  • setDispatcher - Set an action dispatcher;
  • getDispatcher - Get the actions dispatcher;
  • setIoc - Set an inversion of control for controllers;
  • getIoc - Get the inversion of control;
  • setNamespace - Set a namespace;
  • getNamespace - Get the namespace;
  • setErrorAction - Set an error action;
  • getErrorAction - Get the error action;
  • setHost - Set a host;
  • getHost - Get the host.

url

Get the URL of a route.

url(string $name, array $params = []): string

Example:

$router->get('/page/{page}.html', function($page) {
    return "Hello on page {$page}!";
}, 'page');

$router->url('page', ['page' => 'terms']); // result: /page/terms.html

$router->url('page', ['page' => 'terms', 'foo' => 'bar']); // result: /page/terms.html?foo=bar

dispatch

Dispatch an URL path.

dispatch(string $name, array $params = []): string

Example:

echo $router->dispatch('/'); // Dispatch any route

echo $router->dispatch('/user/1', 'POST'); // Dispatch a POST route

Group Route

Magic methods:

Below you can find a list of supported methods.

  • match - Match a path against routes;
  • schema - Get the schema;
  • schemaInfo - Get information about schema;
  • setParent - Set parent routing;
  • getParent - Get parent routing;
  • path - Generate the path;
  • any - Create a route for any request method;
  • request - Create a route for a specific request method;
    • get - Create a GET route;
    • head - Create a HEAD route;
    • post - Create a POST route;
    • put - Create a PUT route;
    • delete - Create a DELETE route;
    • connect - Create a CONNECT route;
    • options - Create a OPTIONS route;
    • trace - Create a TRACE route;
    • patch - Create a PATCH route;
  • hidden - Create a hidden route. You can not dispatch it, but you can generate URLs from it;
  • group - Create a group of routes;
  • find - Find a route by name;
  • bind - Set an input/output binder for a parameter;
  • bindStrategy - Set an input/output binder for a parameter, using strategy;
  • bindIn - Set an input binder for a parameter;
  • bindInStrategy - Set an input binder for a parameter, using strategy;
  • binderIn - Get the input binder of a parameter;
  • bindInParam - Bind an input parameter;
  • bindOut - Set an output binder for a parameter;
  • bindOutStrategy - Set an output binder for a parameter, using strategy;
  • binderOut - Get the output binder of a parameter;
  • bindOutParam - Bind an output parameter;
  • pattern - Set a parameter pattern;
  • type - Set a parameter type;
  • getPattern - Get a parameter pattern;
  • setDispatcher - Set an action dispatcher;
  • getDispatcher - Get the actions dispatcher;
  • setIoc - Set an inversion of control for controllers;
  • getIoc - Get the inversion of control;
  • setNamespace - Set a namespace;
  • getNamespace - Get the namespace;
  • setErrorAction - Set an error action;
  • getErrorAction - Get the error action;
  • setHost - Set a host;
  • getHost - Get the host.

__construct

Initialize the route group.

__construct(string $schema)

Example:

$group = new \Greg\Routing\GroupRoute('/api/v1');

$group->get('/user');

match

Match a path against routes.

match(string $path, ?string $method = null, \Greg\Routing\RouteStrategy &$route = null, \Greg\Routing\RouteData &$data = null): bool

Example:

if ($group->match('/', 'GET', $route, $data)) {
    echo $route->exec($data);
}

Request Route

Magic methods:

Below you can find a list of supported methods.

__construct

Initialize the request route.

__construct(string $schema, $action)

Example:

$route = new \Greg\Routing\RequestRoute('/users', 'UsersController@index');

$route->exec();

match

Match a path against route.

match(string $path, RouteData &$data = null): bool

Example:

if ($route->match('/', $data)) {
    print_r($data->params());
}

exec

Execute the route.

exec(RouteData $data): string

Example:

$route->exec(new RouteData('/', ['foo' => 'bar']));

url

Fetch an URL for the route.

url(array $params = []): string

Example:

$url = $route->url(['foo' => 'bar']);

Hidden Route

Magic methods:

Below you can find a list of supported methods.

__construct

Initialize the request route.

__construct(string $schema)

Example:

$route = new \Greg\Routing\HiddenRoute('/users');

$route->exec();

Routing Abstract

any

Create a route for any request method.

any(string $schema, $action, ?string $name = null): \Greg\Routing\RequestRoute

request

Create a route for a specific request method.

request(string $schema, $action, ?string $name = null, ?string $method = null): \Greg\Routing\RequestRoute

You can also create a specific request method by calling the method name directly. Available types are: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH.

[get|head|post|put|delete|connect|options|trace|patch](string $schema, $action, ?string $name = null): \Greg\Routing\RequestRoute

Example:

$router->get('/users', 'UsersController@index', 'users');

$router->post('/users/add', 'UsersController@add', 'users.add');

hidden

Create a hidden route. You can not dispatch it, but you can generate URLs from it.

hidden(string $schema, string $name): \Greg\Routing\HiddenRoute

Example:

$router->hidden('/catalog/{name}', 'partner.catalog')->setHost('mypartner.com');

$router->url('partner.catalog', ['name' => 'cars']); // result: http://mypartner.com/catalog/cars

group

Create a group of routes.

group(string $schema, ?string $prefix, callable(\Greg\Routing\GroupRoute $route): void $callable): \Greg\Routing\GroupRoute

Example:

$router->group('/api', 'api.', function (\Greg\Routing\GroupRoute $group) {
    $group->group('/v1', 'v1.', function (\Greg\Routing\GroupRoute $group) {
        $group->any('/users', 'UsersController@index', 'users');
    });

    $group->group('/v2', 'v2.', function (\Greg\Routing\GroupRoute $group) {
        $group->any('/users', 'UsersController@index', 'users');
        
        $group->any('/clients', 'ClientsController@index', 'clients');
    });
});

$router->url('api.v1.users'); // result: /api/v1/users

$router->url('api.v1.clients'); // throws: \Greg\Routing\RoutingException

$router->url('api.v2.clients'); // result: /api/v2/clients

find

Find a route by name.

find(string $name): ?\Greg\Routing\FetchRouteStrategy

Example:

$route = $router->find('users.save');

$route->url(['foo' => 'bar']);

setNamespace

Set a namespace.

setNamespace(string $namespace): $this

Example:

$router->setNamespace('Http');

getNamespace

Get the namespace.

getNamespace(): string

BindTrait

bind

Set an input/output binder for a parameter.

bind(string $name, callable(mixed $value): mixed $callableIn, ?callable(mixed $value): mixed $callableOut = null): $this

Example:

$this->bind('id', function($id) {
    $user = (object) ['id' => $id];

    return $user;
}, function($user) {
    return $user->id;
});

bindStrategy

Set an input/output binder for a parameter, using strategy.

bindStrategy(string $name, \Greg\Routing\BindInOutStrategy $strategy): $this

Example:

$this->bindStrategy('id', new class implements BindInOutStrategy {
    public function input($id)
    {
        $user = (object) ['id' => $id];

        return $user;
    }

    public function output($user)
    {
        return $user->id;
    }
});

BindInTrait

bindIn

Set an input binder for a parameter.

bindIn($name, callable(mixed $value): mixed $callable): $this

Example:

$this->bindIn('id', function($id) {
    $user = (object) ['id' => $id];

    return $user;
});

bindInStrategy

Set an input binder for a parameter, using strategy.

bindInStrategy($name, \Greg\Routing\BindInStrategy $strategy): $this

Example:

$this->bindInStrategy('id', new class implements \Greg\Routing\BindInStrategy {
    public function input($id)
    {
        $user = (object) ['id' => $id];

        return $user;
    }
});

binderIn

Get the input binder of a parameter.

binderIn(string $name): \Greg\Routing\BindInStrategy|callable

Example:

$binder = $router->binderIn('id');

if (is_callable($binder)) {
    $user = $binder(1);
} else {
    $user = $binder->input(1);
}

bindInParam

Bind an input parameter.

bindInParam(string $name, $value): mixed

Example:

$user = $router->bindInParam('id', 1);

BindOutTrait

bindOut

Set an output binder for a parameter.

bindOut($name, callable(mixed $value): mixed $callable): $this

Example:

$this->bindOut('id', function($user) {
    return $user->id;
});

bindOutStrategy

Set an output binder for a parameter, using strategy.

bindOutStrategy($name, \Greg\Routing\BindOutStrategy $strategy): $this

Example:

$this->bindOutStrategy('id', new class implements \Greg\Routing\BindOutStrategy {
    public function output($user)
    {
        return $user->id;
    }
});

binderOut

Get the output binder of a parameter.

binderOut(string $name): \Greg\Routing\BindOutStrategy|callable

Example:

$binder = $router->binderOut('id');

if (is_callable($binder)) {
    $id = $binder($user);
} else {
    $id = $binder->output($user);
}

bindOutParam

Bind an output parameter.

bindOutParam(string $name, $value): mixed

Example:

$user = $router->bindOutParam('id', 1);

DispatcherTrait

setDispatcher

Set an action dispatcher.

setDispatcher(callable(mixed $action): mixed $callable): $this

Example:

Let say you want to add the Action suffix to action names:

$router->setDispatcher(function ($action) {
    if (is_callable($action)) {
        return $action;
    }

    return $action . 'Action';
});

getDispatcher

Get the actions dispatcher.

getDispatcher(): callable

setIoc

Set an inversion of control for controllers.

setIoc(callable(string $controllerName): object $callable): $this

Example:

Let say you want instantiate the controller with some custom data, or use some external IoC interface and run the init method if exists.

$router->setIoc(function ($controllerName) {
    // Let say you already have an IoC container.
    global $iocContainer;

    $controller = $iocContainer->load($controllerName);

    if (method_exists($controller, 'init')) {
        $controller->init();
    }

    return $controller;
});

getIoc

Get the inversion of control.

getIoc(): callable

ErrorActionTrait

setErrorAction

Set error action.

setErrorAction($action): $this

Example:

$router->setErrorAction(function() {
    return 'Ooops! Something has gone wrong.'
});

getErrorAction

Get error action.

getErrorAction(): mixed

HostTrait

setHost

Set a host.

setHost(string $host): $this

Example:

$router->setHost('example.com');

getHost

Get the host.

getHost(): string

RoutingTrait

schema

Get the schema.

schema(): ?string

schemaInfo

Get information about schema.

schemaInfo(): ['regex', 'params']

setParent

Set parent routing.

setParent(RoutesAbstract $parent): $this

getParent

Get parent routing.

getParent(): RoutesAbstract

path

Generate the path.

path(array $params = []): array

PatternsTrait

pattern

Set a parameter pattern.

pattern(string $name, string $regex): $this

type

Set a parameter type pattern.

type(string $name, string $type): $this

getPattern

Get parameter pattern.

getPattern(string $name): ?string

License

MIT © Grigorii Duca

Huuuge Quote

I fear not the man who has practiced 10,000 programming languages once, but I fear the man who has practiced one programming language 10,000 times. #horrorsquad