空间 / 路由
包含授权、CORS、嵌套路由的PHP路由
Requires
- php: ^7.4
- psr/http-message: ^1.0
- spatial/psr7: ^1.0
Requires (Dev)
- ext-json: *
This package is auto-updated.
Last update: 2024-09-10 20:48:24 UTC
README
设置 defaultContentType()、enableCache()、allowedMethods()、controllerNamespaceMap() 和 authGuard() 以列出授权(CanActivate 接口)对象
路由负责将请求URI映射到端点选择器,并将传入的请求调度到端点。路由在应用中定义,并在应用启动时配置。路由可以可选地从请求中包含的URL中提取值,然后可以使用这些值进行请求处理。使用应用的路由信息,路由还可以生成映射到端点选择器的URL。
安装
您应该使用Composer安装路由
composer require spatial/route
需要PHP 7.4或更高版本。
路由基本
大多数应用应选择基本且描述性的路由方案,以便URL易于阅读且具有意义。默认的传统路由 {controller=Home}/{action=Index}/{id?}
支持基本且描述性的路由方案。是UI应用的有用起点。开发者在特定情况下(例如,博客和电商端点)通常在应用的高流量区域添加额外的简洁路由,使用属性路由或专用传统路由。
Web API应使用属性路由来将应用的功能建模为一组资源,其中操作由HTTP动词表示。这意味着对同一逻辑资源上的许多操作(例如,GET、POST)将使用相同的URL。属性路由提供了一种控制级别,可以仔细设计API的公共端点布局。
使用方法
在Spatial Web API中,控制器是一个处理HTTP请求的类。控制器的公共方法称为action
methods
或简单称为actions
。当Web API框架收到请求时,它将请求路由到操作。
为了确定调用哪个操作,框架使用路由表。
<?php require '/path/to/vendor/autoload.php'; use Spatial\Router\RouteBuilder; use Spatial\Router\RouterModule; $route = new RouteBuilder(); $route->mapRoute( "DefaultAPI", // name "api/{controller}/{id}", //routeTemplate new class(){ public $id = 2; } //defaults ); // initialize the RouterModule to set routes $appModule = new RouterModule(); $appModule->routeConfig($route); // view results; $appModule->render();
路由表中的每个条目包含一个路由模板。Spatia-Route的设置路由模板是 "api/{controller}/{id}"。在这个模板中,"api"是一个字面路径段,{controller}和{id}是占位符变量。
当库收到HTTP请求时,它会尝试将URI与路由表中的某个路由模板进行匹配。如果没有路由匹配,客户端将收到一个404错误。例如,以下URI与默认路由匹配
-
/api/contacts
-
/api/contacts/1
-
/api/products/gizmo1。然而,以下URI不匹配,因为它缺少"api"段
-
/contacts/1
找到匹配的路由后,Spatia-Route选择控制器和动作
为了找到控制器,Spatia-Route将"Controller"添加到{id}变量的值中。为了找到动作,Spatia-Route查看HTTP动词,然后查找以该HTTP动词命名的动作。例如,对于GET请求,Spatia-Route查找以"Get"开头的行为,如"GetContact"或"AllContacts"。这个约定仅适用于GET、POST、PUT、DELETE、HEAD、OPTIONS和PATCH动词。(您可以通过在控制器上使用属性来启用其他HTTP动词——未来的更新)。我们稍后会看到一个例子。路由模板中的其他占位符变量,如{id},映射到动作参数。让我们看看一个例子。假设您定义以下控制器
<?php use Spatial\Psr7\Response; use Psr\Http\Message\ResponseInterface; public class ProductsController extends ApiController { public function httpGet(int $id): ResponseInterface { $data = [ 'app api', 'value1', 'value2', $id ]; $payload = json_encode($data); $response = new Response(); $response->getBody()->write($payload); return $response; } public function httpDelete(int $id): ResponseInterface{ #code here } }
以下是可能的HTTP请求示例,以及每个请求触发的操作
请注意,如果存在,URI的{id}部分被映射到动作的id参数。在这个例子中,控制器定义了一个带有id参数的GET方法。
此外,请注意,POST请求将失败,因为控制器没有定义“Post...”方法。
按动作名称路由
默认路由模板中,Web API使用HTTP动词来选择动作。然而,您也可以创建一个包含动作名称的路由
<?php $route->mapRoute( "DefaultAPI", "api/{controller}/{action}/{id}", new class(){ public id = 2 } );
在这个路由模板中,{action}参数命名了控制器上的动作方法。
<?php require '/path/to/vendor/autoload.php'; use Spatial\Router\RouteBuilder; use Spatial\Router\RouterModule; $ri = new RouteBuilder(); // create an array or a single of routes $routes = [ $ri->mapRoute( // $name of the routeTemplate and name placeholder for controller namespace 'Api', // $routeTemplate 'api/{controller}/public/{id:int}', // default values for the routeTemplate new class(){ public $id = 3; public $content; function __construct() { $this->content = file_get_contents('php://input'); } } ), $ri->mapRoute( 'SuiteApi', 'suiteapi/{controller}/public/{...param}', new class(){ public $data; } ) ]; // initialize the RouterModule to set routes $appModule = new RouterModule(); $appModule->routeConfig(...$routes) ->allowedMethods('GET, POST, PUT, DELETE') ->enableCache(true) ->authGuard() // takes in list objects for authorization with interface CanActivate ->defaultContentType('application/json') ->controllerNamespaceMap('Spatial\\{name}\\Controllers\\'); // {name} refers to the route name // view results; $appModule->render();
定义路由模板
通过调用Spatial\Router\RouterModule->routeConfig()
函数来定义路由,该函数接受一个接收Spatial\Router\Route
实例的可调用对象。通过在收集器实例上调用mapRoute()
来添加路由
$r->mapRoute($name, $routeTemplate, $defaults);
$name
是一个骆驼命名法的HTTP方法字符串,用于匹配特定路由。可以使用数组指定多个有效方法
如果在路由模板中有占位符,如下所示:suiteapi/{controller}/public/{...param}
,那么前缀为三个字符的...
必须始终放置在路由模板字符串的末尾,因为它代表从该索引开始的剩余URI的数组列表。
示例
假设我们有一个路由
require '/path/to/vendor/autoload.php'; use Spatial\Router\RouteBuilder; use Spatial\Router\RouterModule; $route = new RouteBuilder(); $route->mapRoute( "DefaultAPI", // name "api/{controller}/{...param}", //routeTemplate new class(){ public $id = 2; public $content; function __construct() { $this->content = file_get_contents('php://input'); } } //defaults ); // initialize the RouterModule to set routes $appModule = new RouterModule(); $appModule->routeConfig($route); // view results; $appModule->render();
以及其关联的控制器
<?php use Psr\Http\Message\ResponseInterface; public class ProductsController extends ApiController { public function httpGet(?array $param): ResponseInterface { } public function httpPost(string $content): ResponseInterface { } public function httpPut(string $content, int $id): ResponseInterface{ } }
以下是可能的HTTP请求示例,以及每个请求触发的操作
致谢
此库基于dotNetCore WebAPI框架中的路由器