{"id":15662348,"url":"https://github.com/zofe/burp","last_synced_at":"2025-07-26T01:04:12.943Z","repository":{"id":21805056,"uuid":"25127662","full_name":"zofe/burp","owner":"zofe","description":"simple php router that works with uri, query string or both","archived":false,"fork":false,"pushed_at":"2022-07-19T08:47:55.000Z","size":47,"stargazers_count":18,"open_issues_count":0,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-17T11:07:42.104Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zofe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-12T18:16:00.000Z","updated_at":"2022-07-29T04:00:24.000Z","dependencies_parsed_at":"2022-07-25T12:47:09.708Z","dependency_job_id":null,"html_url":"https://github.com/zofe/burp","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/zofe/burp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zofe%2Fburp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zofe%2Fburp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zofe%2Fburp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zofe%2Fburp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zofe","download_url":"https://codeload.github.com/zofe/burp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zofe%2Fburp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260346861,"owners_count":22995150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T13:31:59.759Z","updated_at":"2025-06-17T11:07:46.655Z","avatar_url":"https://github.com/zofe.png","language":"PHP","readme":"Burp\n============\n\nSimple php __Router__ that can work with \"URI\", \"QUERY STRING\", or both.  \nIt also has a simple __Event__ Listener implementation (to fire or queue application events).\n\nYou can use Burp in your preferred framework (Including laravel), It does not pretend to be the only router, It just check your urls then fire or queue your events.\n\n\n## why\n\nThe idea is to have an \"all in one\" router,filter,event listener.  \nI'ts a way to build event-driven widgets and define a flexible \"semantic\" in application urls\u003cbr /\u003e\n\nBurp can power widgets that works driven by _uri-segments_,_query-string_ or both, without the need to have a classic controller.\n\n## Installation\n\ninstall via composer adding ```\"zofe/burp\": \"3.0.*\"```\n\nif you're using laravel add the service provider in config/app.php:\n    \n    'providers' =\u003e array(\n        ...\n        'Zofe\\Burp\\BurpServiceProvider',\n    )\n    \n## usage\n\nBurp is similar to any other PHP router, but it can also behave as a filter.  \nThere are two main differences you need to know:\n\n  - a route rule can be __strict__ or __not strict__ (It means: \"exact match\", or \"partial match\" i.e. a non strict rule can match some uri-serment or some query-string parameter)\n\n  - rules are non-blocking, It means that a single http request can trigger more than one route \n  \n\n## samples\n\n```php\n\n\u003c?php\n\n\n//catch /user/2 (GET)\nBurp::get('^/user/(\\d+)$', null, array('as'=\u003e'user.show', function($id) {\n    //show user $id\n}));\n\n//catch /user (POST)\nBurp::post('^/user$', null, array('as'=\u003e'user.create', function() {\n    //create new user\n}));\n\n//catch /user/2 (PATCH)\nBurp::patch('^/user/(\\d+)$', null, array('as'=\u003e'user.update', function($id) {\n    //save changes for user $id\n}));\n\n//catch /welcome (on any http method: GET, POST, ...)\nBurp::any('^/welcome/(\\w+)$', null, function($username) {\n    //say welcome $username!\n}));\n\n//catch /something?apikey=xxxx\nBurp::get(null, 'apikey=(\\w+)', array('as'=\u003e'key', function($key) {\n    //check api key in query string..\n}));\n\n//will return: /currenturi?apikey=asda\nBurp::linkRoute('key','asda')\n\nBurp::dispatch();\n```\n\nImportant: \n  - to define a \"strict rule\" you must use regex delimiters  __^__ and __$__\n  - to define a \"parameter\" you must parenthesis as in regex atom \n  \n## bind controllers\n\nyou can bind a route to some __class@method__ using 'uses' key:\n\n```php\n\n\u003c?php\n\n//catch /user/2 (GET)  and bind it to UserController class on show method  \nBurp::get('^/user/(\\d+)$', null, array('as'=\u003e'user.show', 'uses'=\u003e'UsersController@show'));\n\n```\n\n\n## usage - full example as front-controller\n\n\nif you need burp in a \"stand-alone\" context, you need a front controller.  \nYou can start from this .htaccess (most of application framework already have something like this)\n\n\n    RewriteEngine On\n\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteCond %{REQUEST_FILENAME} !-f\n    RewriteRule ^ index.php [L]\n    \nthen you've to include burp, this is a way to have Burp as standalone router:\n\n```php\n\n\u003c?php\n#index.php\n\nrequire_once __DIR__ . '/vendor/autoload.php';\n\nuse Zofe\\Burp\\Burp;\n\n\n//widget routing - fired when url is for example:  /something/pg/2\nBurp::get('pg/(\\d+)', null, array('as'=\u003e'page', function($page) {\n    echo \"current page is page: $page\u003cbr\u003e\";\n}));\n\n//widget routing - fired when url is for example: /something?ord=-title\nBurp::get(null, 'ord=(-?)(\\w+)', array('as'=\u003e'orderby', function($direction, $field) {\n    $direction = ($direction == '-') ? \"descending\" : \"ascending\";\n    echo \"current sorting is on : $field ($direction)\u003cbr\u003e\";\n}))-\u003eremove('page');\n\n\n\n//strict route  - fired when uri is \"/\"  or \"/pg/2\", but not when is \"/something/pag/2\" ...\nBurp::get('^/{page?}$', null, array('as'=\u003e'home', function() {\n\n  echo '\u003chr\u003e';\n  echo '\u003ca href=\"'.Burp::linkRoute('page',1).'\"\u003epage 1\u003c/a\u003e\u003cbr\u003e';\n  echo '\u003ca href=\"'.Burp::linkRoute('page',2).'\"\u003epage 2\u003c/a\u003e\u003cbr\u003e';\n\n  echo '\u003ca href=\"'.Burp::linkRoute('orderby',array('','title')).'\"\u003esort title up\u003c/a\u003e\u003cbr\u003e';\n  echo '\u003ca href=\"'.Burp::linkRoute('orderby',array('-','label')).'\"\u003esort label down\u003c/a\u003e\u003cbr\u003e';\n\n  echo '\u003chr\u003e';\n}));\n\n//404 route  - fired only if there are defined strict routes (i.e.: ^/$ or ^.*$)  \n//but all uncatched\nBurp::missing(function() {\n    header(\"HTTP/1.0 404 Not Found\");\n    echo '404 - Resource Not Found';\n    die;\n});\n\n//where all began\nBurp::dispatch();\n```\n\n## patterns\n\nYou can also declare and use pattern \n\n```php\n\nBurp::pattern('number', '(\\d+)');\nBurp::pattern('page', 'pg/(\\d+)');\nBurp::pattern('slug', '([a-z0-9-]+)');\n\nBurp::get('articles/{page?}',...\nBurp::get('article/{slug}',...\n\n```\nImportant: you must use parenthesis to define the atom/s \n\n\n\n\n\n## usage - in laravel \n\nThis snippet should give you the idea that you can use Burp to:  \n\"define some behavior across laravel routes\".  \n\nThis url: `/article/list?ord=-title` will fire \"sort\"  event.  \nThis url: `/article/list/pg/2?ord=title`  will fire \"sort\" and \"page\" events.\n\nMore, as you know laravel pagination work natively \"only\" with something like this:  \n`/articles/list?page=1`,  but in this sample for this controller It will work via segment:  \n`/articles/list/pg/x` (without to create a custom pagination class).\n\n\n```php\n\n\u003c?php\n\n#in your laravel routes.php add\n\nRoute::pattern('pg', 'pg/(\\d+)');\nRoute::get('/articles/list/{pg?}', array('as'=\u003e'art','uses'=\u003e'ArticleController@getList'));\n\n//define some general purpose events on uri-segments\nBurp::pattern('pg', 'pg/(\\d+)');\nBurp::get('{pg}', null, array('as'=\u003e'page', function($page) {\n     \\Event::queue('page', array($page));\n}));\n//define some general purpose events on query-string\nBurp::get(null, 'ord=(-?)(\\w+)', array('as'=\u003e'orderby', function($direction, $field) {\n    $direction = ($direction == '-') ? \"DESC\" : \"ASC\";\n    \\Event::queue('sort', array($direction, $field));\n}))-\u003eremove('page');\n\nBurp::dispatch();\n\n\n#in your controller \nclass ArticleController extends BaseController {\n\npublic function __construct()\n{\n    //starting from a clean query builder\n    $this-\u003earticles = new Article;\n    \n    //listen for burp defined events\n    \\Event::listen('sort', array($this, 'sort'));\n    \\Event::listen('page', array($this, 'page'));\n    \n    //flush queued events\n    \\Event::flush('sort');\n    \\Event::flush('page');\n}\n\npublic function sort($direction, $field)\n{\n    $this-\u003earticles = $this-\u003earticles-\u003eorderBy($field, $direction);\n}\npublic function page($page)\n{\n    \\Paginator::setCurrentPage($page);\n}\n\npublic function getList()\n{\n    //paginate\n    $articles = $this-\u003earticles-\u003epaginate(20);\n    \n    //fix links to use custom defined pagination-uri (instead classic 'page=?')\n    $links = $articles-\u003elinks();\n    $links = preg_replace('@href=\"(.*\\?page=(\\d+))\"@U', \n                          'href=\"'.Burp::linkRoute('page', '$2').'\"', $links);\n\n    return view('articles.list', compact('articles','links'));\n}\n\n}\n```\n\nNow you are also free to change your url-semantic in your router, for example switching from query-string to uri-segments or viceversa.  \nYou can also move events and common behavior in a base controller  and then extend this one\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzofe%2Fburp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzofe%2Fburp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzofe%2Fburp/lists"}