dataclass可讓您快速將普通array
變更為類型提示的 PHP 類,並自動對嵌入物件和集合進行非規範化,如果您使用規範化器和非規範化器,這通常需要大量工作。該函式庫受到 Python pydantic 模組的啟發。它使用 PHP 7.4 以來提供的類型提示功能。
該套件的主要目標是提供快速的方法來擁有嚴格類型提示的類別以供進一步使用,例如將請求有效負載映射到嚴格類型化的類,以便您可以使用它而不是可能符合您的要求或不符合您的要求的數組。它不會取代您的資料驗證,但會確保 fx 收到的 JSON 負載與您的後端操作期望接收的類型相符。它類似於上面提到的 pydantic BaseModel
或 TypeScript 介面。
您所需要的只是創建一兩個類別:
declare (strict_types= 1 );
class MyEmbededClass
{
public float $ number ;
}
class MyClass
{
public int $ number ;
public ? string $ optionalText = null ;
public MyEmbededClass $ embeded ;
}
下一步傳遞主類別名稱和接收到的數據,例如從接收到的 JSON 到transform
方法:
$ data = ' {
"number": 1,
"embeded": {
"number": 1.23
}
} ' ;
$ object = transform (MyClass::class, json_decode ( $ data , true ));
快速將接收到的資料對應到功能齊全的dataclass :
var_dump ( $ object )
object (MyClass) {
[ " number " ]=> int( 1 )
[ " optionalText " ]=> NULL
[ " embeded " ]=>
object(MyEmbededClass) {
[ " number " ]=>
float( 1.23 )
}
}
您不必擔心從json_decode
傳遞null
,如果偵測到root
字段,它會拋出TransformException
。
您不必擔心丟失字段和無效類型,因為庫會檢測所有類型提示的要求,並拋出TransformException
並拋出帶有錯誤(準備作為響應)的錯誤,該錯誤指向帶有簡單原因消息的確切字段,例如:
echo json_encode ( $ transformException , JSON_PRETTY_PRINT )
{
"errors" : [
{
"field" : " optionalText " ,
"reason" : " Field must have value "
},
{
"field" : " embeded " ,
"reason" : " Field must have value "
}
]
}
您也可以使用Transform::to
方法,該方法實際上是由transform
輔助函數呼叫的。輔助函數將始終使用Transform
物件的最佳設定(一旦它們出現)。
$ data = ' {
"number": 1,
"embeded": {
"number": 1.23
}
} ' ;
$ transformer = new Transform ();
$ object = $ transformer -> to (MyClass::class, json_decode ( $ data , true ));
如果您需要使用具有類型提示參數的建構函數,您可以這樣做,但方式有限。此程式庫僅支援使用有效負載中的值填充建構函數參數。這意味著建構函數必須使用與類別屬性相同的類型和變數名稱。例如:
class MyClass
{
public float $ number ;
public ? int $ numberTwo = null ;
public function __construct ( float $ number )
{
$ this -> number = $ number ;
}
}
對建構函數參數使用不同的名稱或類型將無法運作。目標是支持強制開發商填寫屬性。
任何包含屬性以外的任何其他參數的建構子都會拋出UnsupportedException
。參數必須與屬性具有相同的型別。順序無關緊要。如果需要,在構造函數中只能存在某些屬性子集。
請查看 docs/ 目錄以取得更多範例。
就像這樣簡單
composer install rutek/ dataclass
注意:請注意使用array
類型提示。它們不能被使用(如果偵測到將拋出UnsupportedException
),因為 PHP 不提供對陣列項目進行類型提示的方法。請查看下面的“收藏”部分以獲取更多資訊。
支援所有四個 PHP 標量。
支援類型提示可為空性。您可以安全地使用?string
來接受string
和null
。請注意,僅使用?string $field
並不表示轉換後的陣列可能不包含此欄位。它僅表示該值接受null
。
如果您需要接受不包含某些欄位的資料轉換,您可以使用預設值,例如: ?string $field = null
。 dataclass類別庫將偵測到有效負載中不存在此屬性,並將使用預設值。
PHP 不支援類型提示array
字段,如果您需要嵌入物件或標量的集合,則必須使用Collection
類別。您需要使用具有類型提示參數解構的建構函數來擴展它,例如:
class Tags extends Collection
{
public function __construct ( string ... $ names )
{
$ this -> items = $ names ;
}
}
像string[]
這樣的類型提示數組在 RFC 中被拒絕,因此這種行為可能不會很快改變。
庫將檢查提供的值是否與建構函數的類型提示相符。
無法檢查最小和最大項目,但下一版本可能會有這樣的功能。
請注意,您也可以使用 Collection 作為要轉換的基底類,例如:
$ tags = transform (Tags::class, [ ' tag1 ' , ' tag2 ' ]);
TransformException
- 資料與您的架構不匹配這是您可以預料到的基本異常。每次傳遞給函數transform(string $class, $data)
或Transform::to
的資料(有效負載)與您的類型提示類別不符時,您將收到TransformException
和getErrors(): FieldError[]
方法,該方法描述了真正的內容發生了。
每個FieldError
都包含描述哪個field
未通過類型檢查的欄位以及用簡單的文字描述其被拒絕的reason
。如果存在嵌套對象,您可以期望收到諸如parentProperty.childrenProperty
之類的field
值(以點分隔的層級)。
類別支援 JSON 序列化,並且將始終傳回類似以下內容的內容:
{
"errors" : [
{
"field" : " optionalText " ,
"reason" : " Field must have value "
},
{
"field" : " embeded " ,
"reason" : " Field must have value "
}
]
}
請注意,將來可能會添加code
欄位。
UnsupportedException
- 僅當您的類型提示不受支援時庫並不涵蓋所有場景,因為您可以定義沒有嚴格上下文的類型提示。例如,如果您使用object
屬性,則無法驗證它,因為任何物件都將與您的架構相符。在這種情況下,您可能會遇到UnsupportedException
。
目前不支援 PHP 8.0 聯合類型和 PHP 8.1 交集類型。
目前不支援本機 PHP 8.1 枚舉。
目前,所有類型提示欄位都必須是公共的。實現此類功能是有問題的,因為您必須為此類屬性建立 getter,這是不必要的開銷。庫旨在為從遠端系統(API、佇列/匯流排訊息、瀏覽器)接收的資料定義內部模式創造可能性。
每次呼叫transform
或Transform::to
函數時都會進行所有反射檢查。您很快就能期待快取功能帶來更好的效能。
請記住,這個包的目標不是完全驗證您收到的數據,而是創建簡單的類,這使得您的有效負載在具有一些複雜結構時也能完全類型提示。您不必使用class
欄位對 JSON 中的類別進行編碼,因為您的類型提示將告訴您的程式碼應該建立什麼物件或陣列來取代某些嵌入值。
如果您正在建立 API 並且需要企業級 OpenAPI 模式驗證,您應該檢查 hkarlstrom/openapi-validation-middleware,然後您可以使用此程式庫將接收到的有效負載對應到類型提示類別! :)