获取PHP 7.4中类型化属性的类型

时间:2019-12-05 06:32:50

标签: 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)"正常工作,而不会导致php抛出以下错误:

  

初始化前不得访问类型为App \ Dto \ CreateMembershipInputDto :: $ is_gift的属性

1 个答案:

答案 0 :(得分:2)

尽管该手册目前似乎尚无文档记录,但ReflectionProperty中添加了一种方法,可让您获取类型。实际上是在RFC for typed properties

中指定的

这是您将如何使用它:

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)

请注意,ReflectionType中的getName似乎也没有记录。