PHP 7.4 类型化属性迭代

Rob*_*ert 7 php iteration types php-7 php-7.4

我刚刚发现了一些关于 PHP 7.4 的“有点奇怪”,我不确定是我遗漏了什么,或者它是否是一个实际的错误。大多数情况下,我对您的意见/确认感兴趣。

所以在 PHP 中,你可以像这样迭代对象属性:

class DragonBallClass 
{
    public $goku;
    public $bulma = 'Bulma';
    public $vegeta = 'Vegeta';
}

$dragonBall = new DragonBallClass();

foreach ($dragonBall as $character) {
  var_dump($character);

}

RESULT

NULL
string(5) "Bulma"
string(6) "Vegeta"
Run Code Online (Sandbox Code Playgroud)

现在,如果我们开始使用这样的强类型属性:

class DragonBallClass 
{
    public string $goku;
    public string $bulma = 'Bulma';
    public string $vegeta = 'Vegeta';
}

$dragonBall = new DragonBallClass();

foreach ($dragonBall as $character) {
  var_dump($character);

}
Run Code Online (Sandbox Code Playgroud)

我们会得到不同的结果:

string(5) "Bulma"
string(6) "Vegeta"
Run Code Online (Sandbox Code Playgroud)

现在有什么不同:

当您不为强类型属性分配默认值时,它将是Uninitialized类型的。这当然有道理。问题是,如果它们最终像这样你不能循环它们,它们将被简单地省略 - 没有错误,没有你在第二个例子中看到的任何东西。所以我只是无法访问它们。

这是有道理的,但想象一下你有一个像这样的自定义请求/数据类:

namespace App\Request\Request\Post;

use App\Request\Request\Request;

class GetPostsRequest extends Request
{
    public string $title = '';
}
Run Code Online (Sandbox Code Playgroud)

你看到那个丑陋的字符串分配了吗?如果我想让我的属性在类上可迭代,那么我必须:

  • 掉落类型
  • 分配虚拟值

我可能想要一个具有类型化属性的对象,其中没有任何值来循环它们并在有意义的情况下填充它们。

有没有更好的方法来做到这一点?是否有任何选项可以保持类型并保持可迭​​代性而不必执行这种虚拟值可恶?

Cas*_*yte 8

如果你想允许一个类型化的属性可以为空,你可以简单地?在类型之前添加一个并给出NULL这样的默认值:

class DragonBallClass 
{
    public ?string $goku = NULL;
    public string $bulma = 'Bulma';
    public string $vegeta = 'Vegeta';
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下NULL是一个完全合法的值(而不是一个虚拟值)。

演示


同样不使用?,您始终可以将类属性与对象属性列表合并:

class DragonBallClass 
{
    public string $goku;
    public string $bulma = 'Bulma';
    public string $vegeta = 'Vegeta';
}

$dragonBall = new DragonBallClass();

$classProperties = get_class_vars(get_class($dragonBall));
$objectProperties = get_object_vars($dragonBall);

var_dump(array_merge($classProperties, $objectProperties));

// array(3) {
//  ["goku"]=>
//  NULL
//  ["bulma"]=>
//  string(5) "Bulma"
//  ["vegeta"]=>
//  string(6) "Vegeta"
// }
Run Code Online (Sandbox Code Playgroud)

  • @Robert:还认为给出默认值毕竟是关于您想要赋予属性的类型的精度。换句话说,以空字符串作为默认值的类型字符串与以 NULL 作为默认值的类型字符串是不同的类型;打字的另一面。 (2认同)