greg-md/php-router

强大的PHP路由。

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

This package is auto-updated.

Last update: 2024-09-24 09:37:28 UTC


README

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

强大的PHP路由。

目录

要求

  • PHP版本 ^7.1

工作原理

首先,您必须初始化一个路由器

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

然后,设置一些路由

$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');

如果您设置一个动作如Controller@action,在分发时将实例化UsersController并调用其save公共方法。

现在,您可以分发URL路径

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

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

并且,获取它们的URL

$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

可选,您可以添加一个分发器来管理动作。

假设您想将Action后缀添加到动作名称中

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

    return $action . 'Action';
});

此外,您还可以反转控制器的控制。

假设您想用一些自定义数据实例化控制器,或者使用一些外部IoC接口,并运行存在的init方法。

$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;
});

路由模式

路由模式支持参数可选段

参数格式为{<name>[:<default>][#<type>][|<regex>]}?

<name> - 参数名称;
<default> - 默认值;
<type> - 参数类型。支持intuintboolean(或bool);
<regex> - 参数正则表达式;
? - 端尾的问号确定参数是否可选。

参数中只需要<name>

可选段格式为[<schema>]。是递归工作的。

<schema> - 任何路由模式

当您想使用不同的路由模式使用相同的动作时,这非常有用。

示例

假设我们有一个包含相同类型所有文章的页面,包括分页。此页面的路由将是

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

type参数是必需的,默认值为lifestyle,应包含字母、数字和破折号

page参数在其段中是必需的,但整个段是可选的。默认值为1,应包含无符号整数。如果未设置参数或与默认值相同,整个段将从URL路径中排除。

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

如您所见,没有更多的URL可以获取重复内容,这对SEO最好。这样,您可以轻松创建良好的用户友好的URL。

路由器

以下是可以找到的支持的方法列表。

url

获取路由的URL。

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

示例

$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

分发URL路径。

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

示例

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

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

分组路由

魔法方法

以下是可以找到的支持的方法列表。

__construct

初始化路由组。

__construct(string $schema)

示例

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

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

match

将路径与路由进行匹配;

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

示例

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

请求路由

魔法方法

以下是可以找到的支持的方法列表。

__construct

初始化请求路由。

__construct(string $schema, $action)

示例

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

$route->exec();

match

将路径与路由进行匹配。

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

示例

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

exec

执行路由。

exec(RouteData $data): string

示例

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

url

获取路由的URL。

url(array $params = []): string

示例

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

隐藏路由

魔法方法

以下是可以找到的支持的方法列表。

__construct

初始化请求路由。

__construct(string $schema)

示例

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

$route->exec();

路由抽象

any

为任何请求方法创建路由。

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

request

为特定的请求方法创建路由。

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

您也可以通过直接调用方法名来创建特定的请求方法。可用类型有:GETHEADPOSTPUTDELETECONNECTOPTIONSTRACEPATCH

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

示例

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

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

hidden

创建隐藏路由。您不能分发它,但可以从它生成URL。

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

示例

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

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

group

创建路由组。

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

示例

$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(string $name): ?\Greg\Routing\FetchRouteStrategy

示例

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

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

setNamespace

设置命名空间。

setNamespace(string $namespace): $this

示例

$router->setNamespace('Http');

getNamespace

获取命名空间。

getNamespace(): string

BindTrait

bind

为参数设置输入/输出绑定器。

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

示例

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

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

bindStrategy

使用策略为参数设置输入/输出绑定器。

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

示例

$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

为参数设置输入绑定器。

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

示例

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

    return $user;
});

bindInStrategy

使用策略为参数设置输入绑定器。

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

示例

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

        return $user;
    }
});

binderIn

获取参数的输入绑定器。

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

示例

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

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

bindInParam

绑定输入参数。

bindInParam(string $name, $value): mixed

示例

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

BindOutTrait

bindOut

为参数设置输出绑定器。

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

示例

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

bindOutStrategy

使用策略为参数设置输出绑定器。

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

示例

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

binderOut

获取参数的输出绑定器。

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

示例

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

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

bindOutParam

绑定输出参数。

bindOutParam(string $name, $value): mixed

示例

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

DispatcherTrait

setDispatcher

设置动作分发器。

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

示例

假设您想将Action后缀添加到动作名称中

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

    return $action . 'Action';
});

getDispatcher

获取动作分发器。

getDispatcher(): callable

setIoc

为控制器设置控制反转。

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

示例

假设您想用一些自定义数据实例化控制器,或者使用一些外部IoC接口,并运行存在的init方法。

$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

获取控制反转。

getIoc(): callable

ErrorActionTrait

setErrorAction

设置错误操作。

setErrorAction($action): $this

示例

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

getErrorAction

获取错误操作。

getErrorAction(): mixed

HostTrait

setHost

设置主机。

setHost(string $host): $this

示例

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

getHost

获取主机。

getHost(): string

RoutingTrait

schema

获取架构。

schema(): ?string

schemaInfo

获取架构信息。

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

setParent

设置父级路由。

setParent(RoutesAbstract $parent): $this

getParent

获取父级路由。

getParent(): RoutesAbstract

path

生成路径。

path(array $params = []): array

PatternsTrait

pattern

设置参数模式。

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

type

设置参数类型模式。

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

getPattern

获取参数模式。

getPattern(string $name): ?string

许可

MIT © Grigorii Duca

长篇引用

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