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,然后您可以使用此库将接收到的有效负载映射到类型提示类! :)