monken / ci4-route-attributes
使 CodeIgniter4 路由器支持使用 PHP8 属性语法自动绑定控制器方法和控制器。
Requires
- php: ^8
- codeigniter4/framework: ^4
- haydenpierce/class-finder: ^0.4.3
README
您可以使用此库通过注释定义控制器路由设置,使 CodeIgniter4 能够定义路由设置。
快速演示
namespace App\Controllers; use monken\Ci4RouteAttributes\Route; class Ci4Controller extends BaseController { #[Route(path: 'attr/route', methods: ["get"])] public function hello() { return "PHP8Attributes"; } }
使用 #[Route(path: 'attr/route', methods: ["get"])]
的定义,表示在您的路由配置中完成了相同的设置
$routes->get('attr/route', 'App\Controllers\Ci4Controller::hello');
此库将智能地将您的控制器和路由自动连接起来,这意味着您可以通过 /attr/route
的路径访问 Ci4Controller
中的 hello
方法。
安装指南
需求
- CodeIgniter 框架 4
- Composer
- PHP8↑
Composer 安装
使用 Composer 在项目根目录下下载所需依赖库。
composer require monken/ci4-route-attributes
使用库内置命令初始化所需文件。
php spark route-attr:init
上述命令将对我们的项目进行更改。
app/Config
将有一个RouteAttributes.php
配置文件,您可以通过此文件调整库的执行设置。它看起来像这样<?php namespace Config; use CodeIgniter\Config\BaseConfig; class RouteAttributes extends BaseConfig { /** * Routes are automatically registered only if this is set to `true` * * @var boolean */ public bool $enabled = true; /** * autoscan namespaces * * @var array<string> */ public array $controllerNamespaces = [ "App\Controllers" ]; /** * Generate production environment route definition file path * * @var string */ public string $routeDefinitionFilePath = WRITEPATH . 'cache'; /** * Whether to use pre-generated route definition files in production. * Note that when this option is set to `true`, controller files will not be automatically * scanned in production environment. You must use `route-attr:make` command to generate * route definition files to improve performance in production environment. * * @var boolean */ public bool $productionUseDefinitionFile = true; }
- 自动将库所需的事件写入
app/Config/Events.php
文件的端点,该事件将在 CodeIgniter4 初始化时使用,自动注册路由。该命令将写入以下内容Events::on('pre_system', function(){ \monken\Ci4RouteAttributes\RouteAttributes::runHandler(); });
说明
简而言之,此库是利用 PHP8 属性功能在 CodeIgniter4 路由器下的一种表示方式,它仅对一些 CodeIgniter4 路由器方法提供了一些映射和封装。除此之外,没有其他额外功能。
通过自动扫描控制器内的注释,连接路由和操作,让您能够直接编写路由规则,并以方便的方式维护控制器和路由之间的关系。
生产和开发环境
当您在 CodeIgniter4 框架的开发环境下使用此库时,每次请求发生时,它将重新分析所有控制器类,并处理相应的路由属性。这种策略可以为开发带来最大便利,路由属性的更改将立即生效。然而,在生成环境中,这种策略将导致相当大的性能损失。因此,我们的库提供了一种类似缓存的机制来降低生成环境中的性能损失。
配置文件
您可以在 app/Config/RouteAttributes.php
中找到两个可调整的变量,分别是 routeDefinitionFilePath
和 productionUseDefinitionFile
。
您可以使用 routeDefinitionFilePath
来定义生成环境配置文件的存储位置,默认为 project_root/writable/cache
。
您可以将productionUseDefinitionFile
设置为true
或false
来定义是否在生产环境中激活路由属性定义文件,以实现最佳性能。如果设置为false
,则每次请求生产环境时,都会重新扫描,并在控制器中处理路由属性。
生成路由属性定义文件
您可以使用以下命令生成您的路由属性定义文件,以降低性能损失:
php spark route-attr:make
上述命令将在routeDefinitionFilePath
中定义的路径下生成一个RouteAttributesDefinition
文件。
更新路由属性定义文件
有两种方法可以更新生产环境中的路由属性定义文件:
- 再次运行
php spark route-attr:make
,新内容将直接覆盖旧内容。 - 删除
RouteAttributesDefinition
文件,如果库找不到该文件,它将自动扫描并生成路由属性定义文件。
路由
您可以按照如下方式注册您的路由:
namespace App\Controllers; use monken\Ci4RouteAttributes\Route; class Ci4Controller extends BaseController { #[Route(path: 'attr/route', methods: ["get"])] public function hello() { return "PHP8Attributes"; } }
在此示例中,Path
表示调用此控制器方法的实际路径,而method
将期望您传递一个字符串数组,包括访问此控制器方法所需的HTTP动词。
根据CodeIgniter4的路由全局选项,您可以使用以下动词:add
、get
、post
、put
、head
、options
、delete
、path
和cli
。您可以声明多个动词,以在同一个path
下实现不同method
之间的切换,并访问相同的控制器效果。
选项
您可以将选项数组传递进去,以对路由进行特殊调整,库不会对您的选项进行任何处理或判断,这意味着您必须查阅CodeIgniter4文档来编写正确的选项。通常,此参数将如下所示:
#[Route(path: 'attr/route', methods: ["get"], options:[ 'filter' => 'auth', 'hostname' => 'accounts.example.com' ])]
忽略分组
如果您正在使用RouteGroup
来统一配置同一控制器下的路由,但想要将其中一个单独设置,而不扩展RouteGroup
。您可以设置此参数为true
,使路由成为一个独立的任务,如下所示:
#[Route(path: 'attr/route', methods: ["get"], ignoreGroup: true)]
占位符
您只需关注path
中的占位符配置,库将确定您控制器中的参数数量并完成正确的路由设置。
<?php namespace App\Controllers; use monken\Ci4RouteAttributes\Route; class Ci4Controller extends BaseController { #[Route(path: 'test/(:segment)/(:segment)/(:segment)', methods: ["get"])] public function hello($a, $b, $c) { echo $a . '<br>'; echo $b . '<br>'; echo $c . '<br>'; } }
等于
$route->get('test/(:segment)/(:segment)/(:segment)', 'App\Controllers\Ci4Controller::hello/$1/$2/$3');
单方法声明多个路由
如果您需要,也可以将多个路由设置绑定到单个方法。
namespace App\Controllers; use monken\Ci4RouteAttributes\Route; class Ci4Controller extends BaseController { #[Route(path: 'attr/route', methods: ["get"])] #[Route(path: 'hello/msg', methods: ["get"])] public function hello() { return "PHP8Attributes"; } }
通过上述设置,无论访问attr/route
还是hello/msg
,它们都指向同一个Ci4Controller的hello方法。
RESTful 路由
CodeIgniter4为您提供了方便的RESTful模式,您可以继承相关类以快速实现RESTful设计模式。此库也提供相关模式,帮助您快速将控制器转换为RESTful路由。
资源路由
<?php namespace App\Controllers; use CodeIgniter\RESTful\ResourceController; use monken\Ci4RouteAttributes\RouteRESTful; #[RouteRESTful(name: 'api/user', type: 'resource')] class UserApi extends ResourceController { //... }
等于
$routes->resource('api/user', [ "controller" => 'App\Controllers\UserApi' ]);
name
表示资源名称,也可以声明为路径。在type
上有两个可用的选项,分别命名为resource
和presenter
。
展示者路由
您可以根据需要调整type
的值,将RouteRESTful转换为Presenter Route模式。
<?php namespace App\Controllers; use CodeIgniter\RESTful\ResourcePresenter; use monken\Ci4RouteAttributes\RouteRESTful; #[RouteRESTful(name: 'user', type: 'presenter')] class User extends ResourcePresenter { //... }
等于
$routes->presenter('user', [ "controller" => 'App\Controllers\User' ]);
您可以根据需要调整RouteRESTful的type
,通过设置您的ResourceRoute或PresenterRoute。
websafe
此选项仅在type
采用resource
时才会激活。它将在路由的options
中添加websafe => 1
,使其可用于HTML表单。
#[RouteRESTful(name: 'api/user', websafe: true)]
only
您可以使用only
选项来限制只生成您提到的路由。此参数仅接受一个数组,由方法名称组成。
#[RouteRESTful(name: 'api/user', only: [ 'index', 'show' ])]
有关可接受的方法名称,请参阅我们的文档。
except
您可以使用except
来移除某些路由的生成,此参数只接受一个数组,由方法名组成。
#[RouteRESTful(name: 'api/user', except: [ 'new', 'edit' ])]
有关可接受的方法名称,请参阅我们的文档。
占位符
如果您的API需要资源ID,默认情况下将使用(:segment)
占位符。但您也可以传递placeholder
参数来对其进行更改
#[RouteRESTful(name: 'api/user', placeholder: ':(num)')]
选项
通过传递选项数组到特定于RESTful路由的修订,库不会对您传递的选项进行任何判断。
需要注意的一点是,如果使用了诸如websafe
、only
、except
或placeholder
之类的参数,那么库将自动将您传递的内容与options
数组组合。如果有重复声明,则参数内容将被关注。
您必须参考CodeIgniter4文档来编写正确的选项。通常,此参数的使用方法如下所示
#[RouteRESTful(name: 'api/user', placeholder: ':(num)', options: [ 'filter' => 'auth' ])]
忽略分组
如果您正在使用RouteGroup
来统一配置同一控制器下的路由,但想要将其中的一个单独设置而不扩展RouteGroup
。您可以设置此参数为true
#[RouteRESTful(name: 'api/user', ignoreGroup: true)]
路由分组
通常,您不会希望重新配置重复的path
,例如/api/v1
。因此,您可以使用RouteGroup
将相同的path
或options
统一应用于类下的所有路由设置。
<?php namespace App\Controllers; use monken\Ci4RouteAttributes\Route; use monken\Ci4RouteAttributes\RouteGroup; #[RouteGroup(name: '/route/testgroup', options: ['filter' => 'auth'])] class Group extends BaseController { #[Route(path: 'getindex', methods: ['get'])] public function index() { return "hi"; } #[Route(path: 'get/something', methods: ['get'])] public function somefunction() { return "something"; } }
上级设置等于
$routes->group( '/route/testgroup', ['filter' => 'auth'], function ($routes) { $routes->get('getindex', 'App\Controllers\Group ::index'); $routes->get('get/something', 'App\Controllers\Group ::somefunction'); } );
路由环境
您可以为特定环境创建特殊路由,例如,开发环境中的路由在生产环境和预发布环境中不可用。您可以通过在类中声明RouteEnvironment
来实现此要求。
<?php namespace App\Controllers; use monken\Ci4RouteAttributes\Route; #[RouteEnvironment(type: "development")] class EnvRoute extends BaseController { #[Route(path:'dev/tool', methods:['cli'])] public function devToolMethod() { return "tool msg"; } #[Route(path:'dev/page', methods:['get'])] public function devPageMethod() { return "page msg"; }
上级设置等于
$routes->environment('development', function ($routes) { $routes->cli('dev/tool', 'App\Controllers\EnvRoute::devToolMethod'); $routes->get('dev/page', 'App\Controllers\EnvRoute::devPageMethod'); });
如果需要,RouteEnvironment
也可以与RouteGroup
一起使用
<?php namespace App\Controllers; use monken\Ci4RouteAttributes\Route; use monken\Ci4RouteAttributes\RouteGroup; #[RouteEnvironment(type: "development")] #[RouteGroup('/dev')] class EnvRoute extends BaseController { #[Route(path:'tool', methods:['cli'])] public function devToolMethod() { return "tool msg"; } #[Route(path:'page', methods:['get'])] public function devPageMethod() { return "page msg"; }
上级设置等于
$routes->environment('development', function ($routes) { $routes->group( '/dev', function ($routes) { $routes->cli('tool', 'App\Controllers\EnvRoute::devToolMethod'); $routes->get('page', 'App\Controllers\EnvRoute::devPageMethod'); } ); });