安裝
composer require easyswoole/http-annotation=3.x
組件要求
- php: >=8.1
- ext-json: *
- psr/http-message: ^1.0
- easyswoole/http: 3.x
- ext-mbstring: *
- ext-dom: *
- ext-simplexml: *
- ext-libxml: *
- easyswoole/parsedown: ^1.0
注意:用戶在使用 EasySwoole 注解控制器
進行 EasySwoole
項目開發時,仍需要 use
注解相對應的命名空間。這顯然不是一個高效的做法。我們推薦在 PhpStorm
環境下進行開發,并且在 PhpStorm
中安裝 Jetbrain
自帶的 PHP Annotation
組件,可以提供注解命名空間自動補全、注解屬性代碼提醒、注解類跳轉等非常有幫助的。(PhpStorm 2019
以上版本的 IDE
,該組件可能不能正常使用。)
組件優勢
在使用 EasySwoole Http
注解控制器組件進行開發時,可以很方便地生成 API
接口文檔,可以極大地提高了我們 phper
的開發效率。具體如何使用請看 自動注解文檔 章節。
IDE 提示
當代碼中使用注解與 EasySwoole
提供的 Param
沖突,無法實現 IDE
提示,可以使用別名的方式去使用 EasySwoole
的 Param
注解,代碼如下。
<?php
namespace App\HttpController;
use EasySwoole\HttpAnnotation\AnnotationController;
use EasySwoole\HttpAnnotation\Attributes\Param as ReqParam;
use EasySwoole\HttpAnnotation\Enum\ParamFrom;
use EasySwoole\HttpAnnotation\Validator\Required;
class Index extends AnnotationController
{
#[ReqParam(
name: "deviceId",
from: ParamFrom::JSON,
validate: [
new Required("deviceId is required.")
]
)]
function reportAction()
{
}
}
實現原理
注解控制器,完整命名空間為 EasySwoole\HttpAnnotation\AnnotationController
,是繼承自 use EasySwoole\Http\AbstractInterface\Controller
的子類。它重寫了父類的__hook
方法,從而實現對注解控制器的支持。
__hook
在 __hook
方法中,自動解析使用在當前控制器類上的注解。 該方法是承接 Dispatcher
與控制器實體邏輯的橋梁。在該方法中,注解控制器做了以下事情:
- 檢查當前請求的
http
請求方法是否在當前控制器類的action
允許的請求方法范圍內,來實現過濾非法請求的目的(前提:使用了Api
注解的allowMethod
屬性限制)。 - 讀取在控制器類的
action
中使用的Api
注解信息,讀取在控制器類的 (非靜態非只讀的public
或protected
修飾的) 成員變量中使用的Context/Di/Inject
注解信息并自動給成員變量賦值。 - 檢查并執行成員變量注解邏輯
- 檢查
onRequest
函數注解參數并執行注解參數邏輯校驗 - 檢查使用在
action
上的注解標簽并進行參數校驗與邏輯校驗
基礎示例
<?php
namespace App\HttpController;
use EasySwoole\EasySwoole\Trigger;
use EasySwoole\HttpAnnotation\AnnotationController;
use EasySwoole\HttpAnnotation\Attributes\Param;
use EasySwoole\HttpAnnotation\Exception\ValidateFail;
use EasySwoole\HttpAnnotation\Validator\Required;
class Index extends AnnotationController
{
#[Param(
name: "name",
validate: [
new Required("")
]
)]
#[Param(
name: "age",
validate: [
new Required("")
]
)]
public function index()
{
$data = $this->request()->getRequestParam();
$this->response()->write("your name is {$data['name']} and age {$data['age']}");
}
public function onException(\Throwable $throwable): void
{
if ($throwable instanceof ValidateFail) {
$this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
$this->response()->write("字段【{$throwable->getFailRule()->currentCheckParam()->name}】校驗錯誤");
} else {
Trigger::getInstance()->throwable($throwable);
}
}
}
在以上代碼中,會自動對 name
和 age
字段進行校驗,當校驗失敗時,拋出一個異常,校驗成功則進入 index action
邏輯。具體請看成員屬性注解章節。