zofe / burp
简单的PHP路由器,与查询字符串和uri-segments一起工作,laravel过滤器系统
Requires
- php: >=5.4.0
- illuminate/support: ^5.0|^6.0|^7.0|^8.0|^9.0
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分页默认情况下只与类似此的URL一起工作
/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或相反。
您还可以将事件和常见行为移动到基控制器中,然后扩展该控制器