mrcl / slim-routes
Slim Framework的路由属性
Requires
- php: ^8.1
- slim/slim: ^4.8
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.3
- phpunit/phpunit: ^9.5
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\RouteCollectorInterface
或Slim\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方法映射到您的路由。
默认情况下,它映射到GET
、POST
、PUT
、PATCH
、DELETE
和OPTIONS
(类似于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版本v1
、v2
、v3
。
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-action
和v2-my-action