hnrazevedo/router

Router是一个简单的友好的URL抽象器。

v3.0.6 2021-11-04 18:14 UTC

README

Maintainer Latest Version Scrutinizer Code Quality Build Status Software License PHP from Packagist Total Downloads

Router是一个简单的友好的URL抽象器。它可以轻松实用,既可以以静态方式单独使用,也可以作为中间件或现在与PHP 8一起作为属性使用。它的作者不是开发领域的专业人士,而是一位在技术领域提高自己知识的人。

O Router é um simples abstrator de URL amigável. Ele pode ser utilizado de maneira fácil e prática, tanto individualmente de forma estática, quanto em conjunto como middleware e agora como atributo com o PHP 8. Seu autor não é um profissional da área de desenvolvimento, apenas alguem da área de Tecnologia que está aperfeiçoando seus conhecimentos.

亮点

  • 易于设置(Fácil de configurar)
  • 易于信息缓存(Fácil cacheamento de informações)
  • 遵循标准PSR-15(Segue padrão o PSR-15)
  • Composer ready(Pronto para o composer)

安装

Router可以通过composer.json获取

"hnrazevedo/router": "^2.4" # PHP <= 7.4
"hnrazevedo/router": "^3.0" # PHP >= 8.0

或通过终端

composer require hnrazevedo/router

配置服务器

Nginx

nginx.conf

location / {
    index index.php;
    try_files $uri  /index.php$is_args$args;
}

Apache

.htaccess

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
        Options -Indexes
    </IfModule>

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    <FilesMatch "index.php">
        allow from all
    </FilesMatch>

</IfModule>

文档

有关Router的更多使用和配置信息,请参阅示例文件夹中的组件目标详细信息

有关Router的更多使用和配置信息,请参阅示例文件夹中的组件目标详细信息

错误

在静态使用Router时,如果返回不存在页面错误,将抛出异常

当用作中间件时,返回404响应

在静态使用Router时,如果返回不存在页面错误,将抛出异常;在用作中间件时,返回404响应

访问方法

支持的协议

  • get:URL访问或get方法
  • post:post方法
  • ajax:调用fetch或XMLHttpRequest

Ajax

要使用Ajax调用,需要将REQUEST_METHOD定义为AJAX

要使用Ajax调用,需要将REQUEST_METHOD定义为AJAX

<form>
    <input type="hidden" name="REQUEST_METHOD" value="AJAX" />
    ...
</form>

REST请求

  • post:REST请求
  • get:REST请求
  • put:REST请求
  • delete:REST请求
  • patch:REST请求

Router属性

属性路由与角色路由的工作方式相同,但有几点需要注意

  • 不支持分组;
  • 不支持匿名函数的前后函数;
  • 必须将带有路由的类在管道中声明,并使用路由器加载。

两种声明路由的方式可以一起使用。

属性路由与函数路由的工作方式相同,只是有一些限制

  • 不支持分组;
  • 不支持匿名函数的前后函数;
  • 必须将带有路由的类在管道中声明,并使用路由器加载。

两种声明路由的方式可以一起使用。

use HnrAzevedo\Router\Route;

/**
 * @param string $uri
 * @param ?array $methods
 * @param ?string $name
 * @param ?string $before
 * @param ?string $after
 * @param ?array $middleware
 * @param ?array $attributes
 * @param ?array $where
 */
#[Route('/path', name:'routeName')]

示例

# Controller File
use HnrAzevedo\Router\Route;

class ControllerAttribute{

    #[Route(
        '/user/{id}',
        methods:['GET'],
        name:'routeName',
        before:'Namespace\Controller@methodBefore',
        middleware:[],
        attributes:[
            'attributeName'=>'attributeValue',
            'attributeName0'=>'attributeValue0'
            ],
        where:['id'=>'[0-9]{1,11}'],
        after:'Namespace\Controller@methodAfter',
    )]
    public function method($param)
    {
        echo 'Controller@method executed!'.PHP_EOL."Param:{$param}";
    }

    public function methodBefore(): void
    {
        echo 'methodBefore'.PHP_EOL;
    }

    public function methodAfter(): void
    {
        echo PHP_EOL.'methodAfter';
    }
}

需要以与路由声明文件相同的方式加载带有路由的类,对于两种方法,直接由composer加载都是有趣的。

可以通过类或目录直接进行加载。

需要以与路由声明文件相同的方式加载带有路由的类,对于两种方法,直接由composer加载都是有趣的。

加载可以直接通过类或目录进行

# Pipeline declaration
use HnrAzevedo\Router\Router;

Router::pipeline([
    HnrAzevedo\Router\Example\Controllers\ControllerAttribute::class,
    'examples\Controllers'
]);

路由器方法

get

Router::get('/','App\Controller\Application@method');

post

Router::post('/controller/method','App\Controller\Application@method');

ajax

Router::ajax('/userList','foo\bar\User@listme');

中间件

Router::globalMiddlewares([
    'Authorization'=> \App\Middlewares\Authorization::class
])

Router::get('/foo','foo\bar\User@method')->middleware([
    \App\Middlewares\Authentication::class,
    'Authorization'
]);

name

为路由定义一个名称,如果您想通过名称动态调用

Router::get('/','foo@bar')->name('index');

属性

为路由定义属性,以便动态使用

/**
 * @param string $name
 * @param $value
 */
Router::get('/','foo@bar')->attribute('permission','permissionName');

返回属性

/**
 * @param string $name
 */
$permission = Router::getAttribute('attributeName');

返回所有属性

$permissions = Router::getAttributes();

before

在访问的路由开始工作之前运行

Router::get('/foo/bar','foo@bar')
      ->before('foo@beforeMethod');

Router::get('/foo/bar','foo@bar')
      ->before(function(){
          //
      });

after

在访问的路由工作完成后执行

Router::get('/bar/foo','bar@foo')
      ->after('bar@afterMethod');

Router::get('/bar/foo','bar@foo')
      ->after(function(){
          //
      });

beforeAll

在所有路由的工作之前运行

注意:在 before 方法之前执行 beforeAll 方法

/**
 * @param \Closure|string $action
 * @param ?array $excepts
 */
Router::beforeAll('foo@bar');
Router::beforeAll('foo@bar',['Except_route','Outer_route']);
Router::beforeAll(function(){
          //
      });

after All

在完成所有路由的工作之后运行

注意:在 after 方法之前执行 afterAll 方法

/**
 * @param \Closure|string $action
 * @param ?array $excepts
 */
Router::afterAll('bar@foo');
Router::afterAll('bar@foo',['Except_route','Outer_route']);
Router::afterAll(function(){
          //
      });

group

设置组以使用公共过滤器或 before/after 方法

/**
 * @param string $prefix
 * @param \Closure $definitions
 */
Router::group('/foo', function(){
    Router::post('/bar','foo@bar');
});

groupAttribute

为组中的所有路由定义属性

注意:如果属性已在路由上直接定义,则在此处忽略

/**
 * @param string $name
 * @param $value
 */
Router::group('/foo', function(){
    Router::post('/bar','foo@bar');
})->groupAttribute('permission','permissionName');

groupMiddlewares

为组中的所有成员定义中间件

/**
 * @param array $middlewares
 * @param ?array $excepts
 */
Router::group('/foo', function(){
    //
})->groupMiddlewares([
    'Authorization'
]);

beforeGroup | afterGroup

定义在触发任何组成员之前和之后要采取的操作

/**
 * @param \Closure|string $action
 * @param ?array $excepts
 */
Router::group('/foo', function(){
    Router::post('/bar','foo@bar');
})->beforeGroup(function(){
    //
});

/**
 * @param \Closure|string $action
 * @param ?array $excepts
 */
Router::group('/foo', function(){
    Router::post('/bar','foo@bar');
})->afterGroup(function(){
    //
});

REST

Router::delete('pattern','Namespaces\\Controller:method');
Router::get('pattern','Namespaces\\Controller:method');
Router::post('pattern','Namespaces\\Controller:method');
Router::put('pattern','Namespaces\\Controller:method');
Router::patch('pattern','Namespaces\\Controller:method');

参数

Router::get('/{param}', function($param){
    //
});

Router::get('/{param}/{param2}', function($param, $param2){
    //
});

可选参数

Router::get('/foo/{?id}','foo@bar');

Router::get('/foo/{?any}/{?id}','foo@baz');

Router::get('/user/{?id}/{text}','foo@bat');

正则表达式约束

Router::get('/test/{id}/{id2}',function(){
    //
})->where([
    'id'=>'[0-9]{1,11}',
    'id2' => '[0-9]*'
]);

Router::group('/bar', function(){
    //
})->groupWhere([
    'id'=>'[0-9]{1,11}',
    'id2' => '[0-9]*'
]);

路由定义

协议

/* Unique protocol */
Router::get('/get','foo@bar');

/* Multiple protocols */
Router::match('POST|get|AjAx','/my-account','baz@bar');

/* All protocols */
Router::any('/any','all@met');

当前路由

$route = Router::current();

$name = Router::currentRouteName();

$action = Router::currentRouteAction();

load

/* NOTE: in case of error an exception is thrown */

/* Load the route via the URL accessed on the Router object */
Router::load();
/* Load the route via the name passed to the Router object */
Router::load('bar');

/* After loading the route it is necessary to fire it */
/* NOTE: After loading the route, if any dispatch function name is passed, it will be ignored. */
Router::load('foo')->run();

Router::load();
$currentRouter = Router::current();
Router::run();

run

/* NOTE: in case of error an exception is thrown */

/* Trigger route via URL accessed */
Router::run();
/* Trigger route by the given name */
Router::run('baz');

缓存

/* Returns the routes already defined for caching */
$routes = Router::routes();
/* Pass cached routes to the router */
Router::routes($routes);

SESSION 中缓存的示例

if(!isset($_SESSION['cache']['routes'])){
    //Import routes
    $path = BASEPATH.'/../routes';

    foreach (scandir($path) as $routeFile) {
        if(pathinfo($path.DIRECTORY_SEPARATOR.$routeFile, PATHINFO_EXTENSION) === 'php'){
            require_once($path. DIRECTORY_SEPARATOR .$routeFile);
        }
    }

    $_SESSION['cache']['router']['middlewares'] = Router::globalMiddlewares();
    $_SESSION['cache']['router']['routes'] = Router::routes();
}
    
Router::routes($_SESSION['cache']['router']['routes']);
Router::globalMiddlewares($_SESSION['cache']['router']['middlewares']);

定义顺序

路由加载具有优先级,与静态路由(不带参数)有关

路由加载具有优先级,与静态路由(不带参数)有关

支持

安全:如果您发现任何与安全相关的问题,请通过电子邮件 hnr.azevedo@gmail.com 联系,而不是使用问题跟踪器。

如果您发现任何与安全相关的问题,请通过电子邮件 hnr.azevedo@gmail.com 联系,而不是使用问题跟踪器。

鸣谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件