wepesi / routing
简单轻量级的PHP模块,用于编写干净的Web应用路由
Requires
- php: >=7.4
- ext-json: *
- wepesi/optionsresolver: dev-master
This package is auto-updated.
Last update: 2024-09-30 16:35:39 UTC
README
一个轻量级简单的面向对象的PHP路由器。由Boss Ibrahim Mussa及贡献者构建
功能
- 支持
GET、POST、PUT、DELETE、PATCH请求方法 - 支持如
get()、post()、put()等路由简写 - 静态路由模式
- 动态路由模式:基于PCRE的动态路由模式或基于占位符的动态路由模式
- 可选路由子模式
- 子路由/分组路由
- 允许调用
Class@Method - 路由之前的中间件
- 路由之前/应用之前的中间件
- API分组路由
- 支持
X-HTTP-Method-Override头 - 自定义404
- 在子文件夹中也能正常运行
先决条件/需求
- PHP 7.4或更高版本
- URL重写
安装
可以使用Composer进行安装
composer require wepesi/routing
演示
在demo文件夹中包含一个演示。可以使用您喜欢的Web服务器提供它,或者通过在shell中执行php -S localhost:8080来使用PHP 7.4+'s内置服务器。包含用于Apache的.htaccess文件。
用法
创建一个\Wepesi\Routing\Router实例,将其定义一些路由,然后运行它。
// Require composer autoloader require __DIR__ . '/vendor/autoload.php'; // Create Router instance $router = new \Wepesi\Routing\Router(); // Define routes // ... // Run it! $router->run();
路由
Wepesi/routing支持GET、POST、PUT、PATCH、DELETE HTTP请求方法。传入一个单一的请求方法。
当路由与当前URL(例如$_SERVER['REQUEST_URI'])匹配时,将执行附加的route handling function。路由处理函数必须是一个callable。只有第一个匹配的路由会被处理。当没有找到匹配的路由时,将执行404处理器。
路由简写
提供单一请求方法的简写
$router->get('pattern', function() { /* ... */ }); $router->post('pattern', function() { /* ... */ }); $router->put('pattern', function() { /* ... */ }); $router->delete('pattern', function() { /* ... */ });
注意:必须在调用$router->run();之前挂钩路由。
路由模式
路由模式可以是静态的或动态的
- 静态路由模式不包含动态部分,必须与当前URL的
path部分完全匹配。 - 动态路由模式包含可以随请求而变化的动态部分。这些变化的部分被称为
subpatterns,并使用Perl兼容正则表达式(PCRE)或使用placeholders进行定义
静态路由模式
静态路由模式是一个表示URI的普通字符串。它将直接与当前URL的path部分进行比较。
示例
/about/contact
使用示例
// This route handling function will only be executed when visiting http(s)://www.example.org/about $router->get('/about', function() { echo 'About Page Contents'; });
基于占位符的动态路由模式
这种类型的路由模式与基于PCRE的动态路由模式相同,但有一个区别:它们不使用正则表达式进行模式匹配,而是使用更简单的placeholders。占位符是包围在冒号中的字符串,例如:name。
示例
/movies/:id/profile/:username
占位符比PCRE更容易使用,但提供的控制较少,因为它们在内部被转换为匹配任何字符的正则表达式(.*)。
$router->get('/movies/:movieId/photos/:photoId', function($movieId, $photoId) { echo 'Movie #' . $movieId . ', photo #' . $photoId; });
注意:占位符的名称应与传递给路由处理函数的参数名称匹配。
基于PCRE的动态路由模式
此类路由模式包含动态部分,这些部分在每个请求中可能不同。这些可变部分称为子模式,并使用正则表达式定义。
使用示例
// This route handling function will only be executed when visiting http(s)://www.example.org/movies/3 $router->get('/movies/:id', function($id) { echo 'Get a movie by ID:'.$id; })->with('id','[0-9]+');
在动态路由模式中常用到的基于PCRE的子模式包括
\d+= 一个或多个数字(0-9)\w+= 一个或多个单词字符(a-z 0-9 _)[a-z0-9_-]+= 一个或多个单词字符(a-z 0-9 _)和连字符(-).*= 任何字符(包括/),零个或多个[^/]+= 除了/之外的任何字符,一个或多个
当定义了多个子模式时,结果的路由处理参数将按照它们定义的顺序传递到路由处理函数的`with`函数中
// http(s)://www.example.org/articles/12-nyiragongo-volcano` $router->get('/artilces/:id-:name', function($id, $title) { echo 'Articles #' . $id . ', title #' . $title; }) ->with('id','[0-9]+') ->with('title','[a-z\0-9]+');
这可以看作是对参数的一种验证。
子路由/分组路由
使用$router->group($baseroute, $fn)将一组路由分组到一个子路由模式中。子路由模式会作为前缀添加到作用域中定义的所有后续路由。例如,将回调$fn挂载到/movies将/movies添加到所有后续路由的前缀。
$router->group('/movies', function() use ($router) { // will result in '/movies/' $router->get('/', function() { echo 'movies overview'; }); // will result in '/movies/id' $router->get('/:id', function($id) { echo 'movie id ' . $id; }); });
子路由可以嵌套,只需在已包含在先前$router->group()中的可调用函数中定义第二个$router->group()即可。
$router->group('/articles', function() use ($router) { // will result in '/articles/' $router->get('/', function() { echo 'articles overview'; }); // $router->group('/themes', function() use ($router) { // will result in '/articles/themes' $router->get('/', function() { echo 'Articles themes overview'; }); // will result in '/articles/themes/4' $router->get('/:id', function($id) { echo 'Articles themes detail id: ' . $id; }); }); });
Class#Method调用
我们可以这样路由到类操作
$router->get('/users/:id', '\Wepesi\Controller\UserController#get_users_detail');
或
$router->get('/users/:id', [\Wepesi\Controller\UserController::class,'get_users_detail']);
当请求匹配指定的路由URI时,UserController类上的get_users方法将被执行。定义的路由参数将被传递到类方法。
该方法可以是静态的(不推荐)或非静态的(推荐)。在非静态方法的情况下,将创建该类的新实例。
$router->get('/users/profile', \Wepesi\Controller\Users::profile());
注意:如果您正在使用静态方法,请不要将其作为字符串或数组传递。
路由中间件之前
wepesi/routing支持Before Route Middlewares,这些中间件在路由处理之前执行。
$router->get('/articles/:id', function($id) { echo "article id is:".$id; })->middleware(function($id){ if(!filter_var($id,FILTER_VALIDATE_INT)){ echo "you should provide an integer"; exit; } });
路由中间件是针对路由的,可以设置一个或多个中间件,并在路由函数之前执行。
$router->get('/admin/:id', function($id) { echo "admin id is:".$id; })->middleware(function($id){ print_r("First middleware"); })->middleware(function($id){ print_r("Second middleware"); })->middleware(function($id){ print_r("Last middleware before Route function"); });
API分组路由
您可以在api方法中定义您的API路由,并自动完成API路由。
$router->api('/v1',function() use($router){ $router->group('/users',function() use($router){ $router->get('/',[appController::class,'getUsers']); }); }); // output // /api/v1/users
覆盖请求方法
使用X-HTTP-Method-Override来覆盖HTTP请求方法。仅当原始请求方法是POST时才有效。允许的X-HTTP-Method-Override值为PUT、DELETE或PATCH。
自定义404
默认的404处理器设置404状态代码并退出。您可以使用$router->set404(callable)来覆盖默认的404处理器。
$router->set404(function() { header('HTTP/1.1 404 Not Found'); // ... do something special here });
您还可以定义多个自定义路由,例如,如果您想定义一个/api路由,您可以打印自定义的404页面
$router->set404('**)?', function() { header('HTTP/1.1 404 Not Found'); header('Content-Type: application/json'); $jsonArray = array(); $jsonArray['status'] = "404"; $jsonArray['status_text'] = "route not defined"; echo json_encode($jsonArray); });
还支持Class@Method调用
$router->set404([appController::class,'notfound']);
当没有路由模式匹配当前URL时,将执行404处理器。
💡您还可以通过调用$router->trigger404()手动触发404处理器
与其他库的集成
通过使用use关键字将依赖项传递到处理函数中,将其他库与wepesi/routing集成。
$view = new \Wepesi\View(); $router->get('/', function() use ($view ) { $view->assign('email','ibmussafb@gmail.com'); $view->assign('github','bim-g'); $view->display("/profile.php"); }); $router->run();
给定这个结构,仍然可以在After Router Middleware中操纵输出
关于PUT操作的工作说明
PHP中没有$_PUT这样的东西。必须伪造它
$router->put('/movies/:username', function($username) { // Fake $_PUT $_PUT = array(); parse_str(file_get_contents('php://input'), $_PUT); // ... });
子目录支持
$router->api('/v1',function() use($router){ include __DIR__.'/router/users.php'; });
许可证
wepesi/routing在Apache-2.0许可证下发布。有关详细信息,请参阅附带的LICENSE文件。