di-zatech/burp

一个简单的PHP路由器,与查询字符串和uri-segments一起工作,laravel过滤器系统

维护者

详细信息

github.com/dizatech/burp

源代码

v3.1.5 2024-02-25 15:24 UTC

This package is auto-updated.

Last update: 2024-09-25 16:53:26 UTC


README

一个简单的php 路由器,可以与 "URI","查询字符串" 或两者同时工作。
它还包含一个简单的 事件监听器 实现(用于触发或队列应用程序事件)。

您可以在您首选的框架中使用Burp(包括laravel),它并不试图成为唯一的路由器,它只是检查您的URL然后触发或队列事件。

为什么

理念是拥有一个“一站式”的路由器、过滤器、事件监听器。
这是一种构建事件驱动的控件和定义灵活的“语义”应用程序URL的方法

Burp可以为受 uri-segments查询字符串 或两者驱动的控件供电,而无需拥有经典的控制器。

安装

使用composer安装,添加 "zofe/burp": "3.0.*"

如果您正在使用laravel,请将服务提供者在config/app.php中添加

'providers' => array(
    ...
    'Zofe\Burp\BurpServiceProvider',
)

用法

Burp类似于任何其他PHP路由器,但它也可以作为过滤器使用。
您需要了解的两个主要区别是

  • 路由规则可以是 严格非严格(这意味着:“精确匹配”或“部分匹配”,即非严格规则可以匹配一些uri-segment或一些查询字符串参数)

  • 规则是非阻塞的,这意味着单个HTTP请求可以触发多个路由

示例

<?php


//catch /user/2 (GET)
Burp::get('^/user/(\d+)$', null, array('as'=>'user.show', function($id) {
    //show user $id
}));

//catch /user (POST)
Burp::post('^/user$', null, array('as'=>'user.create', function() {
    //create new user
}));

//catch /user/2 (PATCH)
Burp::patch('^/user/(\d+)$', null, array('as'=>'user.update', function($id) {
    //save changes for user $id
}));

//catch /welcome (on any http method: GET, POST, ...)
Burp::any('^/welcome/(\w+)$', null, function($username) {
    //say welcome $username!
}));

//catch /something?apikey=xxxx
Burp::get(null, 'apikey=(\w+)', array('as'=>'key', function($key) {
    //check api key in query string..
}));

//will return: /currenturi?apikey=asda
Burp::linkRoute('key','asda')

Burp::dispatch();

重要

  • 要定义“严格规则”,您必须使用正则表达式的界定符 ^$
  • 要定义“参数”,您必须使用括号,就像正则表达式原子一样

绑定控制器

您可以使用'uses'键将路由绑定到某个 class@method

<?php

//catch /user/2 (GET)  and bind it to UserController class on show method  
Burp::get('^/user/(\d+)$', null, array('as'=>'user.show', 'uses'=>'UsersController@show'));

用法 - 前端控制器完整示例

如果您需要“独立”上下文中的Burp,您需要一个前端控制器。
您可以从这个 .htaccess开始(大多数应用程序框架已经有了类似的东西)

RewriteEngine On

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

然后您需要包含burp,这是将Burp作为独立路由器的一种方式

<?php
#index.php

require_once __DIR__ . '/vendor/autoload.php';

use Zofe\Burp\Burp;


//widget routing - fired when url is for example:  /something/pg/2
Burp::get('pg/(\d+)', null, array('as'=>'page', function($page) {
    echo "current page is page: $page<br>";
}));

//widget routing - fired when url is for example: /something?ord=-title
Burp::get(null, 'ord=(-?)(\w+)', array('as'=>'orderby', function($direction, $field) {
    $direction = ($direction == '-') ? "descending" : "ascending";
    echo "current sorting is on : $field ($direction)<br>";
}))->remove('page');



//strict route  - fired when uri is "/"  or "/pg/2", but not when is "/something/pag/2" ...
Burp::get('^/{page?}$', null, array('as'=>'home', function() {

  echo '<hr>';
  echo '<a href="'.Burp::linkRoute('page',1).'">page 1</a><br>';
  echo '<a href="'.Burp::linkRoute('page',2).'">page 2</a><br>';

  echo '<a href="'.Burp::linkRoute('orderby',array('','title')).'">sort title up</a><br>';
  echo '<a href="'.Burp::linkRoute('orderby',array('-','label')).'">sort label down</a><br>';

  echo '<hr>';
}));

//404 route  - fired only if there are defined strict routes (i.e.: ^/$ or ^.*$)  
//but all uncatched
Burp::missing(function() {
    header("HTTP/1.0 404 Not Found");
    echo '404 - Resource Not Found';
    die;
});

//where all began
Burp::dispatch();

模式

您还可以声明和使用模式

Burp::pattern('number', '(\d+)');
Burp::pattern('page', 'pg/(\d+)');
Burp::pattern('slug', '([a-z0-9-]+)');

Burp::get('articles/{page?}',...
Burp::get('article/{slug}',...

重要:您必须使用括号来定义原子/s

用法 - 在laravel中

这个片段应该让您了解您可以使用Burp来
“定义跨laravel路由的行为”。

此URL: /article/list?ord=-title 将触发“sort”事件。
此URL: /article/list/pg/2?ord=title 将触发“sort”和“page”事件。

此外,如您所知,laravel分页“原生的”只与类似此的 /articles/list?page=1 一起工作
但是在这个示例中,对于这个控制器,它将通过段来工作
/articles/list/pg/x(无需创建自定义分页类)。

<?php

#in your laravel routes.php add

Route::pattern('pg', 'pg/(\d+)');
Route::get('/articles/list/{pg?}', array('as'=>'art','uses'=>'ArticleController@getList'));

//define some general purpose events on uri-segments
Burp::pattern('pg', 'pg/(\d+)');
Burp::get('{pg}', null, array('as'=>'page', function($page) {
     \Event::queue('page', array($page));
}));
//define some general purpose events on query-string
Burp::get(null, 'ord=(-?)(\w+)', array('as'=>'orderby', function($direction, $field) {
    $direction = ($direction == '-') ? "DESC" : "ASC";
    \Event::queue('sort', array($direction, $field));
}))->remove('page');

Burp::dispatch();


#in your controller 
class ArticleController extends BaseController {

public function __construct()
{
    //starting from a clean query builder
    $this->articles = new Article;
    
    //listen for burp defined events
    \Event::listen('sort', array($this, 'sort'));
    \Event::listen('page', array($this, 'page'));
    
    //flush queued events
    \Event::flush('sort');
    \Event::flush('page');
}

public function sort($direction, $field)
{
    $this->articles = $this->articles->orderBy($field, $direction);
}
public function page($page)
{
    \Paginator::setCurrentPage($page);
}

public function getList()
{
    //paginate
    $articles = $this->articles->paginate(20);
    
    //fix links to use custom defined pagination-uri (instead classic 'page=?')
    $links = $articles->links();
    $links = preg_replace('@href="(.*\?page=(\d+))"@U', 
                          'href="'.Burp::linkRoute('page', '$2').'"', $links);

    return view('articles.list', compact('articles','links'));
}

}

现在您也可以自由更改您的URL-语义在您的路由器中,例如从查询字符串切换到uri-segments或反之亦然。
您还可以将事件和常见行为移动到基控制器中,然后扩展此控制器