php - 在 PHP 7.4 中获取类型化属性的类型
问题描述
我有一个DTO
带类型的 PHP 变量:
class CreateMembershipInputDto extends BaseDto
{
public bool $is_gift;
public int $year;
public string $name;
public \DateTime $shipping_date;
public ContactInputDto $buyer;
public ?ContactInputDto $receiver;
}
我正在尝试制作某种自动映射器来填充属性,但是我需要检查变量的类型,但这似乎是不可能的。
class BaseDto
{
public function __construct($json)
{
$jsonArray = json_decode($json, true);
foreach($jsonArray as $key=>$value){
$type = gettype($this->$key);
if($type instanceof BaseDto)
$this->$key = new $type($value);
else
$this->$key = $value;
}
}
}
ContactInputDto:
class ContactInputDto extends BaseDto
{
public string $firstname;
public string $lastname;
public string $street_housenumber;
public string $postal_code;
public string $place;
public string $country;
public string $email;
public string $phone;
}
是否有可能使该行"gettype($this->$key)"
工作,而不会引发以下错误:
类型化属性 App\Dto\CreateMembershipInputDto::$is_gift 在初始化之前不得访问
解决方案
虽然该手册目前似乎没有记录它,但添加了一种方法ReflectionProperty
来允许您获取类型。这实际上是在RFC 中为类型化属性指定的
以下是您将如何使用它:
class CreateMembershipInputDto extends BaseDto {
public bool $is_gift;
public int $year;
public string $name;
public \DateTime $shipping_date;
public ContactInputDto $buyer;
public ?ContactInputDto $receiver;
}
class BaseDto
{
public function __construct($json)
{
$r = new \ReflectionClass(static::class); //Static should resolve the the actual class being constructed
$jsonArray = json_decode($json, true);
foreach($jsonArray as $key=>$value){
$prop = $r->getProperty($key);
if (!$prop || !$prop->getType()) { continue; } // Not a valid property or property has no type
$type = $prop->getType();
if($type->getName() === BaseDto::class) //types names are strings
$this->$key = new $type($value);
else
$this->$key = $value;
}
}
}
如果您想检查类型是否扩展BaseDto
,您将需要(new \ReflectionClass($type->getName()))->isSubclassOf(BaseDto::class)
注意getName
指的是ReflectionNamedType::getName
。在 PHP 8 之前,这是您可以获得的唯一可能的实例,$prop->getType()
但是从 PHP 8 开始,您可能还会获得一个ReflectionUnionType
包含多种类型的实例
推荐阅读
- wordpress - 联系表格 7 MailChimp 扩展程序无法正常工作
- c# - 我的触发器对撞机触发,但里面的 if 语句不起作用
- c++ - 在多个时间戳执行函数
- java - Java中的列表内列表
- listview - Flutter 上 Listview 的快照长度
- firebase - 比较firestore中的资源和请求资源
- vue.js - 显示消息取决于 v-on:click in vue
- c++ - How to pass a single row of a 2D vector as a function argument
- javascript - RxJS:限制速率限制的 API 调用
- cmake - 如何将外部项目 SDL_mixer 添加到使用 SDL 1.2 的项目中?