在 php 中为对象/关联数组解构赋值数值数组解构 (PHP 7.1)关联数组解构 (PHP 7.1)对象解构 (PHP 7.1)请勿使用extract

2022-08-30 09:10:22

在CoffeeScript,Clojure,ES6和许多其他语言中,我们对对象/映射/等进行了解构,有点像这样:

obj = {keyA: 'Hello from A', keyB: 'Hello from B'}
{keyA, keyB} = obj

我在php中找到了list函数,它允许您像这样分解数组:

$info = array('coffee', 'brown', 'caffeine');
list($drink, $color, $power) = $info;

有没有办法在PHP中分解对象或关联数组?如果不是在核心库中,也许有人写了一些智能助手函数?


答案 1

对于 PHP 7.0 及更低版本,这超出了 的功能范围。文档指出:list

list 仅适用于数字数组,并假定数字索引从 0 开始。

可能适合您目的的一件事是 extract() 函数,它将变量从数组导入到当前交易品种表中。虽然您可以显式定义变量名称,但不会给您这种自由。listextract()

提取关联数组

你可以做这样的事情:extract

<?php

$info = [ 'drink' => 'coffee', 'color' => 'brown', 'power' => 'caffeine' ];
extract($info);

var_dump($drink); // string(6) "coffee"
var_dump($color); // string(5) "brown"
var_dump($power); // string(8) "caffeine"

提取对象

提取对象的工作原理几乎相同。由于仅将数组作为参数,因此我们需要将对象属性作为数组获取。get_object_vars为您做到这一点。它返回一个关联数组,其中所有公共属性为键,其值为值。extract

<?php

class User {

    public $name = 'Thomas';

}

$user = new User();
extract( get_object_vars($user) );

var_dump($name); // string(6) "Thomas"

陷阱

extract()与 不同,因为它不允许您显式定义导出到符号表的变量名称。默认情况下,变量名称对应于数组键。list

  • list是一种语言构造,而它是一个函数extract()
  • 您可能会无意中覆盖事先定义的变量
  • 数组键作为变量名称可能无效

使用可以作为第二个参数传递给的参数,可以在发生冲突或变量无效时影响行为。但是,了解其工作原理并将其与考顿一起使用仍然很重要。$flagsextract()extract()

编辑:从 PHP 7.1 开始,这是可能的:

http://php.net/manual/en/migration71.new-features.php#migration71.new-features.support-for-keys-in-list

现在,您可以在 list() 或其新的速记 [] 语法中指定键。这样就可以解构具有非整数或非顺序键的数组。

https://php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring

速记数组语法 ([]) 现在可用于分解赋值的数组(包括在 foreach 内),作为现有 list() 语法的替代方法,该语法仍然受支持。

例如:

$test_arr = ['a' => 1, 'b' => 2];
list('a' => $a, 'b' => $b) = $test_arr;
var_dump($a);
var_dump($b);

将从 7.1.0 开始输出以下内容

int(1) 
int(2)

答案 2

我注意到接受的答案遗漏了使用速记符号的示例,使用提取的安全问题以及IDE问题。

数值数组解构 (PHP 7.1)

从 PHP 7.1 开始,支持数值数组解构(Symetric array destructuring),如下所示:

<?php
$data = [55, 'John', 'UK'];
[$id, $name] = $data; // short-hand (recommended)
list($id, $name) = $data; // long-hand

请注意,如果您不想要它们,您可能会错过它们。

关联数组解构 (PHP 7.1)

您还可以取消组织关联数组(支持列表中的键),如下所示:

<?php
$data = ['id' => 55, 'firstName' => 'John', 'country' => 'UK']
['id' => $id, 'firstName' => $name] = $data; // short-hand (recommended)
list('id' => $id, 'firstName' => $name) = $data; // long-hand

请注意,如果您不想要它们,您可能会错过它们。此外,变量名称也可以与属性名称不同。

对象解构 (PHP 7.1)

不幸的是,没有对象解构。但是,您可以使用get_object_vars将对象转换为关联数组,然后使用关联数组解构。

<?php
class User {
    public $id;
    public $name;
    public $country;
}

$user = new User();
$user->id = 55;
$user->name = 'John';
$user->country = 'UK';

['id' => $id, 'firstName' => $name] = get_object_vars($user)

但是,这可能会破坏某些 IDE 功能。这些是我在使用PHPStorm 2019.1时注意到的一些问题:

  • IDE 可能不再理解变量的类型,因此您需要添加一些 PHPDocs 来维护自动完成功能@var Type
  • 不能很好地与重构工具配合使用。例如,如果重命名其中一个属性,则数组解构部分也不会自动重命名。

所以我建议以正常的方式去做:

$id = $user->id
$name = $user->firstName

请勿使用extract

使用提取时,始终设置所有变量。在那里,使用它是一个非常糟糕的主意,因为:

  • 它可能导致安全问题。即使你小心翼翼,将来也可能导致不明显的安全漏洞。如果您确实使用它,请不要将其与用户输入(例如,)一起使用,除非您想制造恶意黑客的一天。$_GET$_POST
  • 可能导致难以检测的错误
  • 如果类或数组将来发生更改,则通过引入新属性,如果它与已使用的变量重合,则可能会破坏代码,除非您使用标志或类似EXTR_SKIP

推荐