安裝
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
項目開發(fā)時,仍需要 use
注解相對應(yīng)的命名空間。這顯然不是一個高效的做法。我們推薦在 PhpStorm
環(huán)境下進行開發(fā),并且在 PhpStorm
中安裝 Jetbrain
自帶的 PHP Annotation
組件,可以提供注解命名空間自動補全、注解屬性代碼提醒、注解類跳轉(zhuǎn)等非常有幫助的。(PhpStorm 2019
以上版本的 IDE
,該組件可能不能正常使用。)
組件優(yōu)勢
在使用 EasySwoole Http
注解控制器組件進行開發(fā)時,可以很方便地生成 API
接口文檔,可以極大地提高了我們 phper
的開發(fā)效率。具體如何使用請看 自動注解文檔 章節(jié)。
IDE 提示
當(dāng)代碼中使用注解與 EasySwoole
提供的 Param
沖突,無法實現(xiàn) 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()
{
}
}
實現(xiàn)原理
注解控制器,完整命名空間為 EasySwoole\HttpAnnotation\AnnotationController
,是繼承自 use EasySwoole\Http\AbstractInterface\Controller
的子類。它重寫了父類的__hook
方法,從而實現(xiàn)對注解控制器的支持。
__hook
在 __hook
方法中,自動解析使用在當(dāng)前控制器類上的注解。 該方法是承接 Dispatcher
與控制器實體邏輯的橋梁。在該方法中,注解控制器做了以下事情:
- 檢查當(dāng)前請求的
http
請求方法是否在當(dāng)前控制器類的action
允許的請求方法范圍內(nèi),來實現(xiàn)過濾非法請求的目的(前提:使用了Api
注解的allowMethod
屬性限制)。 - 讀取在控制器類的
action
中使用的Api
注解信息,讀取在控制器類的 (非靜態(tài)非只讀的public
或protected
修飾的) 成員變量中使用的Context/Di/Inject
注解信息并自動給成員變量賦值。 - 檢查并執(zhí)行成員變量注解邏輯
- 檢查
onRequest
函數(shù)注解參數(shù)并執(zhí)行注解參數(shù)邏輯校驗 - 檢查使用在
action
上的注解標(biāo)簽并進行參數(shù)校驗與邏輯校驗
基礎(chǔ)示例
<?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
字段進行校驗,當(dāng)校驗失敗時,拋出一個異常,校驗成功則進入 index action
邏輯。具體請看成員屬性注解章節(jié)。