mrcl/slim-routes

Slim Framework的路由属性

0.0.1 2021-12-27 11:44 UTC

This package is auto-updated.

Last update: 2024-09-21 17:04:07 UTC


README

Slim提供PHP8属性,以便更轻松、更干净的路由。

目录

安装

SlimRoutes需要 >= PHP 8.1

composer require mrcl/slim-routes

使用

属性

控制器

#[Controller] 将控制器类标记为可路由。

use Mrcl\SlimRoutes\Attribute\Controller;

#[Controller]
class UserController
{...}

控制器参数

路由

#[Route] 将路由映射到操作。
默认情况下,它使用GET方法。

use Mrcl\SlimRoutes\Attribute\Route;

#[Route('users/{id}')]
class ViewUserAction
{
    public function __invoke
}

Routes:
-> GET /users/{id}
use Mrcl\SlimRoutes\Attribute\Controller;
use Mrcl\SlimRoutes\Attribute\Route;
use Mrcl\SlimRoutes\Routing\HttpMethod;

#[Controller('users')]
class UserController
{
    #[Route('{id}')]
    public function getUser

    #[Route(method: HttpMethod::POST)]
    public function addUser
}

Routes:
-> GET  /users/{id}
-> POST /users

路由参数

配置

最小配置

对于最小配置,您只需传递一个Slim/App实例(或任何实现了Slim\Interfaces\RouteCollectorInterfaceSlim\Interfaces\RouteCollectorProxyInterface的类)以及您的操作/控制器类所在的目录。

use Mrcl\SlimRoutes\SlimRoutes;
use Slim\Factory\AppFactory;

$app = AppFactory::create();
$sr = new SlimRoutes(
    $app,
    __DIR__ . '/../src'
);
$sr->registerRoutes();

注意:#[Controller(version, groupId)]#[Route(version. groupId, priority)]没有配置将无法工作。

配置选项

缓存

推荐用于生产环境。

$sr->enableCache($cacheFile)

额外目录

添加另一个目录以搜索可路由类。

$sr->addDirectory($directory)

文件名模式

您可以通过设置文件名/扩展名模式(正则表达式)来最小化扫描的类数量。
如果您在文件夹中有许多其他类并且/或您不使用缓存(例如在开发中),则建议使用此功能。

$sr->setFileNamePattern($fileNamePattern, $fileExtensionPattern = 'php')

示例
所有想要的文件名都以'Controller'结尾,文件扩展名为'php'或'PHP'

Regex: /^(.+Controller)\.(php|PHP)$/
setFileNamePattern('.+Controller', 'php|PHP')

*Action.php*Controller.php文件提供的选项已经准备好使用。

$sr->useActionFilePattern($fileExtensionPattern = 'php')
// OR
$sr->useControllerFilePattern($fileExtensionPattern = 'php')

$sr->addGroup($groupConfiguration)

有关更多信息,请参阅使用组的高级分组

API版本

$sr->addApiVersion($versionConfiguration)

有关更多信息,请参阅API版本控制

路由优先级

如果您想优先考虑您的路由,您需要首先启用它。在RoutePriority中提供了预定义的常量。

$sr->enableRoutePrioritization($defaultPriority = RoutePriority::NORMAL)

如果您计划使用自己的优先级范围,您可以通过传递一个defaultPriority来传递。优先级是简单的整数,数字越小,优先级越高(在路由堆栈中的位置越好)。

更改ANY映射

特殊的HttpMethod::ANY将“任何”HTTP方法映射到您的路由。

默认情况下,它映射到GETPOSTPUTPATCHDELETEOPTIONS(类似于Slim)。

您可以配置它以满足您的需求

$sr->setAnyHttpMethods($methods, $override = true)

更多信息

路由模式

开头斜杠

您可能已经注意到,本文档中的所有路由模式都没有使用开头的/。它们在路由生成时自动添加。
如果您喜欢使用开头的斜杠,请随意使用。

模式顺序

根据Slim配置,基本路径或组可以是第一个模式元素。

[/Slim][/ApiVersion][[/Parent...Group]/Group][/Controller]/Route

中间件

与Slim不同,添加的中间件按照您设置的顺序运行。

#[Controller('users', [FirstMiddleware::class, SecondMiddleware::class])]
class UserController {
    #[Route(middleware: [ThirdMiddleware::class, FourthMiddleware::class])] 
    public function getAllUsers
}

Request > FirstMiddleware > SecondMiddleware > ThirdMiddleware > FourthMiddleware
UserController:getAllUsers
第四个中间件 > 第三个中间件 > 第二个中间件 > 第一个中间件 > 响应`

中间件顺序

在Slim级别添加的中间件总是首先运行。

[SlimMiddleware][ApiVersionMiddleware][[父组...中间件]组中间件][控制器中间件][路由中间件]

HTTP方法

SlimRoutes带有预定义的HTTP方法常量,这些方法是最常用的。
另请参阅,更改ANY的映射

路由分组

控制器模式

通过使用#[Controller]属性,您可以传递一个pattern,它将作为类中所有路由的前缀。

#[Controller('users')]
class UserController {
    #[Route] 
    public function getAllUsers
    
    #[Route('{id}')]
    public function getUser
}

Routes:
-> GET /users
-> GET /users/{id}

使用分组的高级分组

如果您只想将动作类分组或需要更复杂的路由设置,而不想经常重新分配模式和中间件,您可以在路由中配置要使用的分组。

您可以使用一个额外的类来定义GroupConfiguration

use Mrcl\SlimRoutes\Routing\GroupConfiguration;

class Group
{
    final public const ANIMALS   = 'animals';
    final public const CATS      = 'cats';
    final public const ELEPHANTS = 'elephants';

    private array $groups;

    public function __construct()
    {
        $this->groups = [
            self::ANIMALS => ($animals = new GroupConfiguration(id: self::ANIMALS, pattern: 'animals', middleware: AnimalsMiddleware::class)),
            self::ELEPHANTS => new GroupConfiguration(id: self::ELEPHANTS, pattern: 'elephants', middleware: ElephantsMiddleware::class, parent: $animals),
            self::CATS => new GroupConfiguration(id: self::CATS, pattern: 'cats', middleware: CatsMiddleware::class, parent: $animals)
        ];
    }

    public function get(string $id): GroupConfiguration
    {
        return $this->groups[$id];
    }
}

将分组添加到SlimRoutes

$sr
  //->addGroup(Group->get(Group::ANIMALS)) you only need to add a group if you use it directly 
  ->addGroup(Group->get(Group::CATS)) 
  ->addGroup(Group->get(Group::ELEPHANTS))

传递分组ID

#[Controller(groupId: Group::CATS)]
class CatsController {
    #[Route] 
    public function getAllCats
    
    #[Route('{id}')]
    public function getCat
}

Routes:
-> GET /animals/cats      [AnimalsMiddleware, CatsMiddleware]
-> GET /animals/cats/{id} [AnimalsMiddleware, CatsMiddleware]
#[Route(method: HttpMethod::POST, groupId: Group::ELEPHANTS)]
class AddElephantAction
{
    public function __invoke
}

Routes:
-> POST /animals/elephants [AnimalsMiddleware, ElephantsMiddleware]

API版本控制

要为所有路由启用API版本控制,您必须配置一个VersionConfiguration

$sr->addApiVersion(new VersionConfiguration(version: 'v1', middleware: MyMiddleware::class))

多个API版本

假设您有三个API版本v1v2v3

  • v1仅用于一些旧路由,例如/v1/updates
  • v3是最新的,刚刚上线,用户正在更新中
  • v2仍被大多数用户使用

可能的配置可能如下所示

use Mrcl\SlimRoutes\Routing\VersionConfiguration;

$sr
  ->addApiVersion(new VersionConfiguration(version: 'v1', middleware: ApiV1Middleware::class, priority: RoutePriority::LOW, default: false))
  ->addApiVersion(new VersionConfiguration(version: 'v2', middleware: ApiV2Middleware::class))
  ->addApiVersion(new VersionConfiguration(version: 'v3', middleware: [ApiMiddleware::class, OtherApiMiddleware::class]))
  ->enableApiVersionPrioritization()
  ...

路由顺序

路由堆栈将包含以下顺序的路由

/v3/route1
/v2/route1
/v3/route2
/v2/route2
... 
all v3 and v2 routes
...
/v1/...

您仍然可以在路由上使用priority参数来降低或提高其位置。

特定路由的版本控制

我们有以下额外的配置

  ...
  ->addRouteGroup(new GroupConfiguration(id: 'cats-v1', pattern: 'cats'))
  ->addRouteGroup(new GroupConfiguration(id: 'cats', pattern: 'cats', middleware: CatsMiddleware::class))
  ->enableRoutePrioritization()

对于控制器设置,可能的配置可以是

#[Controller(groupId: 'cats')]
class CatController {
    #[Route] 
    public function getAllCats
    
    #[Route(
      pattern: 'all', 
      groupId: 'cats-v1', 
      version: 'v1'
    )] 
    public function getAllCatsV1
}

Routes:
-> GET /v3/cats     [ApiMiddleware, OtherApiMiddleware, CatsMiddleware]
-> GET /v2/cats     [ApiV2Middleware, CatsMiddleware]
-> GET /v1/cats/all [ApiV1Middleware]

对于动作类

#[Route(groupId: 'cats')] 
class ViewCatsAction {
    public function __invoke
}
#[Route(
  pattern: 'all', 
  groupId: 'cats-v1', 
  version: 'v1'
)] 
class ViewCatsActionV1 {
    public function __invoke
}

无版本路由

仅排除一些路由

如果您想排除一些路由的版本控制,可以将VersionConfiguration::NONE传递给#[Route]#[Controller]属性。

#[Route(
  pattern: 'my-action', 
  version: VersionConfiguration::NONE
)]
class MyAction
{
    public function __invoke
}

此外,如果您的所有未版本化路由都需要特定的中间件,您可以添加一个VersionConfiguration

$sr->addApiVersion(new VersionConfiguration(VersionConfiguration::NONE, SomeMiddleware::class, default: false))

使所有路由都无版本可用

如果您有特殊情况,即所有路由(没有特定的版本分配)也需要无版本访问,您可以这样做

$sr->addApiVersion(new VersionConfiguration(VersionConfiguration::NONE))

有版本的路由名称

当您添加API版本并使用路由名称时,路由名称将添加前缀版本。

$sr
  ->addApiVersion(new VersionConfiguration('v1'))
  ->addApiVersion(new VersionConfiguration('v2'))
#[Route(name: 'my-action')]
class MyAction
{
    public function __invoke
}

路由名称是v1-my-actionv2-my-action