空间/路由

包含授权、CORS、嵌套路由的PHP路由

v1.0.2 2020-03-31 14:54 UTC

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框架中的路由器