承接 rareloop/router 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

rareloop/router

Composer 安装命令:

composer require rareloop/router

包简介

A powerful PHP Router for PSR7 messages inspired by the Laravel API

README 文档

README

Latest Stable Version CI Coverage Status

A simple PHP router built on AltoRouter but inspired by the Laravel API.

Installation

composer require rareloop/router

Usage

Creating Routes

Map

Creating a route is done using the map function:

use Rareloop\Router\Router;

$router = new Router;

// Creates a route that matches the uri `/posts/list` both GET 
// and POST requests. 
$router->map(['GET', 'POST'], 'posts/list', function () {
    return 'Hello World';
});

map() takes 3 parameters:

  • methods (array): list of matching request methods, valid values:
    • GET
    • POST
    • PUT
    • PATCH
    • DELETE
    • OPTIONS
  • uri (string): The URI to match against
  • action (function|string): Either a closure or a Controller string

Route Parameters

Parameters can be defined on routes using the {keyName} syntax. When a route matches that contains parameters, an instance of the RouteParams object is passed to the action.

$router->map(['GET'], 'posts/{id}', function(RouteParams $params) {
    return $params->id;
});

If you need to add constraints to a parameter you can pass a regular expression pattern to the where() function of the defined Route:

$router->map(['GET'], 'posts/{id}/comments/{commentKey}', function(RouteParams $params) {
    return $params->id;
})->where('id', '[0-9]+')->where('commentKey', '[a-zA-Z]+');

// or

$router->map(['GET'], 'posts/{id}/comments/{commentKey}', function(RouteParams $params) {
    return $params->id;
})->where([
    'id', '[0-9]+',
    'commentKey', '[a-zA-Z]+',
]);

Optional route Parameters

Sometimes your route parameters needs to be optional, in this case you can add a ? after the parameter name:

$router->map(['GET'], 'posts/{id?}', function(RouteParams $params) {
    if (isset($params->id)) {
        // Param provided
    } else {
        // Param not provided
    }
});

Named Routes

Routes can be named so that their URL can be generated programatically:

$router->map(['GET'], 'posts/all', function () {})->name('posts.index');

$url = $router->url('posts.index');

If the route requires parameters you can be pass an associative array as a second parameter:

$router->map(['GET'], 'posts/{id}', function () {})->name('posts.show');

$url = $router->url('posts.show', ['id' => 123]);

If a passed in parameter fails the regex constraint applied, a RouteParamFailedConstraintException will be thrown.

HTTP Verb Shortcuts

Typically you only need to allow one HTTP verb for a route, for these cases the following shortcuts can be used:

$router->get('test/route', function () {});
$router->post('test/route', function () {});
$router->put('test/route', function () {});
$router->patch('test/route', function () {});
$router->delete('test/route', function () {});
$router->options('test/route', function () {});

Setting the basepath

The router assumes you're working from the route of a domain. If this is not the case you can set the base path:

$router->setBasePath('base/path');
$router->map(['GET'], 'route/uri', function () {}); // `/base/path/route/uri`

Controllers

If you'd rather use a class to group related route actions together you can pass a Controller String to map() instead of a closure. The string takes the format {name of class}@{name of method}. It is important that you use the complete namespace with the class name.

Example:

// TestController.php
namespace \MyNamespace;

class TestController
{
    public function testMethod()
    {
        return 'Hello World';
    }
}

// routes.php
$router->map(['GET'], 'route/uri', '\MyNamespace\TestController@testMethod');

Creating Groups

It is common to group similar routes behind a common prefix. This can be achieved using Route Groups:

$router->group('prefix', function ($group) {
    $group->map(['GET'], 'route1', function () {}); // `/prefix/route1`
    $group->map(['GET'], 'route2', function () {}); // `/prefix/route2§`
});

Middleware

PSR-15/7 Middleware can be added to both routes and groups.

Adding Middleware to a route

At it's simplest, adding Middleware to a route can be done by passing an object to the middleware() function:

$middleware = new AddHeaderMiddleware('X-Key1', 'abc');

$router->get('route/uri', '\MyNamespace\TestController@testMethod')->middleware($middleware);

Multiple middleware can be added by passing more params to the middleware() function:

$header = new AddHeaderMiddleware('X-Key1', 'abc');
$auth = new AuthMiddleware();

$router->get('route/uri', '\MyNamespace\TestController@testMethod')->middleware($header, $auth);

Or alternatively, you can also pass an array of middleware:

$header = new AddHeaderMiddleware('X-Key1', 'abc');
$auth = new AuthMiddleware();

$router->get('route/uri', '\MyNamespace\TestController@testMethod')->middleware([$header, $auth]);

Adding Middleware to a group

Middleware can also be added to a group. To do so you need to pass an array as the first parameter of the group() function instead of a string.

$header = new AddHeaderMiddleware('X-Key1', 'abc');

$router->group(['prefix' => 'my-prefix', 'middleware' => $header]), function ($group) {
    $group->map(['GET'], 'route1', function () {}); // `/my-prefix/route1`
    $group->map(['GET'], 'route2', function () {}); // `/my-prefix/route2§`
});

You can also pass an array of middleware if you need more than one:

$header = new AddHeaderMiddleware('X-Key1', 'abc');
$auth = new AuthMiddleware();

$router->group(['prefix' => 'my-prefix', 'middleware' => [$header, $auth]]), function ($group) {
    $group->map(['GET'], 'route1', function () {}); // `/my-prefix/route1`
    $group->map(['GET'], 'route2', function () {}); // `/my-prefix/route2§`
});

Defining Middleware on Controllers

You can also apply Middleware on a Controller class too. In order to do this your Controller must extend the Rareloop\Router\Controller base class.

Middleware is added by calling the middleware() function in your Controller's __constructor().

use Rareloop\Router\Controller;

class MyController extends Controller
{
    public function __construct()
    {
        // Add one at a time
        $this->middleware(new AddHeaderMiddleware('X-Key1', 'abc'));
        $this->middleware(new AuthMiddleware());

        // Add multiple with one method call
        $this->middleware([
            new AddHeaderMiddleware('X-Key1', 'abc',
            new AuthMiddleware(),
        ]);
    }
}

By default all Middleware added via a Controller will affect all methods on that class. To limit what methods Middleware applies to you can use only() and except():

use Rareloop\Router\Controller;

class MyController extends Controller
{
    public function __construct()
    {
        // Only apply to `send()` method
        $this->middleware(new AddHeaderMiddleware('X-Key1', 'abc'))->only('send');

        // Apply to all methods except `show()` method
        $this->middleware(new AuthMiddleware())->except('show');

        // Multiple methods can be provided in an array to both methods
        $this->middleware(new AuthMiddleware())->except(['send', 'show']);
    }
}

Matching Routes to Requests

Once you have routes defined, you can attempt to match your current request against them using the match() function. match() accepts an instance of Symfony's Request and returns an instance of Symfony's Response:

$request = Request::createFromGlobals();
$response = $router->match($request);
$response->send();

Return values

If you return an instance of Response from your closure it will be sent back un-touched. If however you return something else, it will be wrapped in an instance of Response with your return value as the content.

Responsable objects

If you return an object from your closure that implements the Responsable interface, it's toResponse() object will be automatically called for you.

class MyObject implements Responsable
{
    public function toResponse(RequestInterface $request) : ResponseInterface
    {
        return new TextResponse('Hello World!');
    }
}

$router->get('test/route', function () {
    return new MyObject();
});

404

If no route matches the request, a Response object will be returned with it's status code set to 404;

Accessing current route

The currently matched Route can be retrieved by calling:

$route = $router->currentRoute();

If no route matches or match() has not been called, null will be returned.

You can also access the name of the currently matched Route by calling:

$name = $router->currentRouteName();

If no route matches or match() has not been called or the matched route has no name, null will be returned.

Using with a Dependency Injection Container

The router can also be used with a PSR-11 compatible Container of your choosing. This allows you to type hint dependencies in your route closures or Controller methods.

To make use of a container, simply pass it as a parameter to the Router's constructor:

use MyNamespace\Container;
use Rareloop\Router\Router;

$container = new Container();
$router = new Router($container);

After which, your route closures and Controller methods will be automatically type hinted:

$container = new Container();

$testServiceInstance = new TestService();
$container->set(TestService::class, $testServiceInstance);

$router = new Router($container);

$router->get('/my/route', function (TestService $service) {
    // $service is now the same object as $testServiceInstance
});

rareloop/router 适用场景与选型建议

rareloop/router 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 185k 次下载、GitHub Stars 达 92, 最近一次更新时间为 2017 年 07 月 13 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「router」 「rareloop」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 rareloop/router 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 rareloop/router 我们能提供哪些服务?
定制开发 / 二次开发

基于 rareloop/router 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 185k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 92
  • 点击次数: 18
  • 依赖项目数: 3
  • 推荐数: 0

GitHub 信息

  • Stars: 92
  • Watchers: 12
  • Forks: 9
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2017-07-13