c9s/roller

高性能PHP路由器

1.9.1 2013-08-10 14:57 UTC

This package is not auto-updated.

Last update: 2024-09-14 12:51:54 UTC


README

PHP Roller 是一个简单快速的PHP路由器。

Roller 将您的路由编译成一个简单的数组来存储路由,因此它很快。

除此之外,Roller 提供了一个扩展来提高您的性能。

Build Status

特性

  • 高度可定制
  • 灵活
  • 简单的 DSL(类似 Sinatra 语法)
  • 支持 APC 缓存。
  • 支持文件缓存。
  • 内置的 RESTful 路由生成器,资源处理器。
  • 可定制的 RESTful 路由生成器,资源处理器。
  • 简单、有用的路由路径语法。 (类似 Rails 风格)
  • 高性能(通过 PHP 扩展,比纯 PHP 版本快 1607%
  • 高单元测试覆盖率,覆盖率 > 88%
  • 适用于框架。
  • 支持注解读取器。

基准测试

ROUTE CONSOLE DUMPER

安装

使用 Composer 安装

{
    "require": {
        "corneltek/roller": "~1.8"
    }
}

通过 PEAR 安装

pear channel-discover pear.corneltek.com
pear install corneltek/Roller

或克隆此仓库

pear install -f package.xml

将此库作为 git 子模块使用:克隆此仓库,选择一个 PSR-0 类加载器,并将 src/ 添加到类路径。

要使用控制台转储器,您需要 ezc/ConsoleTools,请使用 PEAR 安装程序进行安装

pear channel-discover components.ez.no
pear install -a ezc/ConsoleTools

概述

Roller 路由器为您提供了一个简单的 DSL 来声明类似 Sinatra 的路由

require 'bootstrap.php';
require 'Roller/DSL.php';

on('/path/to/:date',function() {


    return 'your content';
});

on('/path/to/:year', [ ':year' => '\d+' ] ,function() {

    return 'your content';
});

dispatch( $_SERVER['PATH_INFO'] );

更多用法

初始化一个路由器

$router = new Roller\Router;

添加一个使用简单回调的新路由

$router->add( '/blog/:id/:title'  , function($id,$title) { 
    return 'Blog';
});

添加一个使用类回调的新路由

$router->add( '/blog/:year/:month/:id/:title'  , array('Controller','method') );

添加一个使用类/操作回调字符串的新路由

$router->add( '/path/to/blog'  , 'Controller:methodName' );

添加一个有要求的新路由

$router->add( '/path/to/:year' , array('Callback','method') , array( 
    ':year' => '\d+',
));

添加一个有要求和闭包的新路由

$router->add( '/path/to/:year' , function($year) { 
    return $year;
},array( 
    ':year' => '\d+',
));

或通过 any

$router->any( '/path/to/:year' , function($year) { 
    return $year;
}, array( 
    ':year' => '\d+',
));

GET 方法的别名

$router->get( '/path/to/:year' , function($year) { ... } );

POST 方法的别名

$router->post( '/path/to/:year' , function($year) { ... } );

元属性

Roller 当前支持: methoddefaultrequirementpostget 属性。

添加一个有要求和默认值的新路由

$router->add( '/path/to/:year' , array('Callback','method') , array( 
    ':year' => '\d+',
    'default' => array(
        'year' => 2000,
    ),
));

添加一个有请求方法(如 POST 方法)的新路由

$router->add( '/path/to/:year' , array('Callback','method') , array( 
    ':year' => '\d+',

    'method' => 'post',
    'default' => array(
        'year' => 2000,
    ),
));

RouteSet

RouteSet 是一个路由集合类,您可以将路由集合挂载到另一个路由集合。

使用 RouteSet 非常简单

$subroutes = new Roller\RouteSet;
$subroutes->add( '/subitem' , $cb );

$routes = new Roller\RouteSet;
$routes->mount( '/item' , $subroutes );

挂载路径

挂载路由集合

$routes = new Roller\RouteSet;
$routes->add( '/path/to/:year' , array( 'Callback', 'method' ) );

$routes = new Roller\RouteSet;
$routes->mount( '/root' , $routes );

$router = new Roller\Router( $routes );

分发

分发路径

$r = $router->dispatch( $_SERVER['PATH_INFO'] );

评估响应内容

if( $r !== false )
    echo $r();
else
    die('page not found.');

自定义路由类

class YourRoute extends Roller\MatchedRoute
{
    // customze here.
}

$r = new Roller\Router(array( 
    'route_class' => 'YourRoute'
));
$route = $r->dispatch( '/path/to/...' );    // get YourRoute object.

为控制器使用注解读取器

class AnnotationTestController {

    /**
     * @Route("/hello/:name", name="_hello", requirements={":name" = ".+"}, vars={ "k" = 123, "b" = 234 })
     */
    function helloAction($name) { 
        return $name;
    }

    /**
     * @Route("/")
     */
    function indexAction() {
        return 'index';
    }
}

$router = new Roller\Router;
$router->importAnnotationMethods( 'AnnotationTestController' , '/Action$/' );
$route = $router->dispatch('/');
$route(); // returns 'index'

$route = $router->dispatch('/hello/John');
$route();  // returns "John"

缓存

启用 apc 缓存

$router = new Roller\Router( null , array( 
    'cache_id' => '_router_testing_'
));

启用文件缓存

$router = new Roller\Router( null , array( 
    'cache_id' => '_router_testing_',
    'cache_dir' => 'tests/cache',
));

RESTful 接口

Roller Router 有一个内置的 RESTful 路由生成器,定义一系列 RESTful 路由非常简单,Roller Router 还提供了一个简单的 RESTful 路由生成器,自定义自己的 RESTful 路由也很简单。

首先,初始化一个 RESTful 插件对象

$router = new Roller\Router;
$restful = new Roller\Plugin\RESTful(array( 
        'prefix' => '/restful' 
));

将 RESTful 插件添加到您的路由器管理器

$router->addPlugin($restful);

支持 RESTful 的两种解决方案

  • ResourceHandler:如果您需要为每个资源定义不同的逻辑,您可以使用 ResourceHandler,您可以将不同的资源逻辑分离到不同的处理器类中。
  • GenericHandler:如果您的资源使用相同的逻辑和相同的权限控制,您可以为每个资源使用 GenericHandler

使用 ResourceHandler,将您的资源 ID 注册到路由器中,与您的资源处理器类名相关联,每个资源 ID 都映射到一个资源处理器

$restful->registerResource( 'blog' , 'BlogResourceHandler' );

定义您的资源处理器,以下是一个简单的博客示例,它定义了 RESTful CRUD 的工作方式

use Roller\Plugin\RESTful\ResourceHandler;

class BlogResourceHandler extends ResourceHandler
{
    public function create()    { 
        $this->codeCreated();
        return array( 'id' => 1 );
    }

    public function update($id) 
    {
        $put = $this->parseInput();
        return array( 'id' => 1 );
    }

    // delete a record.
    public function delete($id) 
    {
        return array( 'id' => 1 );
    }

    // load one record
    public function load($id)   { return array( 'id' => $id , 'title' => 'title' ); }

    // find records
    public function find()      { 
        return array( 
            array( 'id' => 0 ),
            array( 'id' => 1 ),
            array( 'id' => 2 ),
        );
    }
}

关于状态码,请参见下面的列表

  • codeOk (200)
  • codeCreated (201)
  • codeAccepted (202)
  • codeNoContent (204)
  • codeBadRequest (400)
  • codeForbidden (403)
  • codeNotFound (404)

在您分发URL之前,路由对象会调用ResourceHandler类的expand方法,该方法将RESTful路由生成到路由对象的路由集中。下面是生成的URL

GET /restful/blog        - get blog list
GET /restful/blog/:id    - get one blog record
POST /restful/blog       - create one blog record
PUT /restful/blog/:id    - update one blog record
DELETE /restful/blog/:id - delete one blog record

您可以重写expand方法来定义自己的RESTful URL风格。

现在您应该能够分发RESTful URL了

$_SERVER['REQUEST_METHOD'] = 'get';
$r = $router->dispatch('/restful/blog/1');

// returns {"success":true,"data":{"id":"1","title":"title"},"message":"Record 1 loaded."}
$r();   

$_SRVER['REQUEST_METHOD'] = 'get';
$r = $router->dispatch('/restful/blog');

// {"success":true,"data":[{"id":0},{"id":1},{"id":2}],"message":"Record find success."}
$r();

自定义资源处理器

下面是RESTful路由生成器的工作方式

    static function expand($routes, $h, $r)
    {
        $routes->add( "/$r(\.:format)" , array($h,'handleFind'), 
            array( 
                'get' => true , 
                'default' => array( 'format' => 'json' ) 
            ));

        $routes->add( '/' . $r . '(\.:format)' , array($h,'handleCreate'), 
            array( 
                'post' => true, 
                'default' => array( 'format' => 'json' ) 
            ));

        $routes->add( '/' . $r . '/:id(\.:format)' , array($h,'handleLoad'),
            array( 
                'get' => true, 
                'default' => array( 'format' => 'json' )
            ));

        $routes->add( '/' . $r . '/:id(\.:format)' , array($h,'handleUpdate'),
            array( 
                'put' => true, 
                'default' => array( 'format' => 'json' ) 
            ));

        $routes->add( '/' . $r . '/:id(\.:format)' , array($h,'handleDelete'),
            array( 
                'delete' => true, 
                'default' => array( 'format' => 'json' ) 
            ));
    }

要定义自己的RESTful资源处理器(生成器),您只需从Roller\Plugin\RESTful\ResourceHandler类继承即可

use Roller\Plugin\RESTful\ResourceHandler;

class YourResourceHandler extends ResourceHandler {

    // define your own expand method
    static function expand( $routes , $handlerClass, $resourceId ) {

    }

}

Apache的<.htaccess>文件

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ your_router.php/$1 [NC,L]

安装扩展

$ cd extension
$ phpize 
$ ./configure 
$ make && make install

将配置添加到您的php.ini中

extension=roller.so

破解

运行Composer安装

composer install --dev

安装ConsoleTools

pear channel-discover components.ez.no
pear install -a ezc/ConsoleTools

获取Onion并安装它

$ curl -s http://install.onionphp.org/ | bash

运行onion来安装依赖项

$ onion install

现在您应该能够运行phpunit了=)

$ phpunit tests

待办事项

  • 可扩展控制器(内部的路由表)
  • 自动可扩展控制器(根据方法名自动扩展路由)