在php中为对象/关联数组进行解构赋值

时间:2015-01-30 09:36:15

标签: php destructuring

在CoffeeScript,Clojure,ES6和许多其他语言中,我们对对象/贴图/等进行了解构,如下所示:

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

我在php中找到了list function,它允许你像这样构造数组:

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

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

3 个答案:

答案 0 :(得分:27)

对于PHP 7.0及更低版本,超出了list的功能。文档声明:

  

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

可能适合您的目的之一是extract()函数,它将数组中的变量导入当前符号表。使用list时,您可以明确定义变量名称,extract()不会给您这种自由。

提取关联数组

使用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"

提取对象

提取对象的工作方式几乎相同。由于extract仅将数组作为参数,因此我们需要将对象属性作为数组。 get_object_vars为你做到了。它返回一个关联数组,其中所有 public 属性为键,其值为value。

<?php

class User {

    public $name = 'Thomas';

}

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

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

<强>陷阱

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

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

使用$flags参数作为第二个参数传递给extract(),可以在碰撞或无效变量的情况下影响行为。但是,知道extract()如何工作并将其与cauton一起使用仍然很重要。

编辑:从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)

答案 1 :(得分: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)

您还可以像这样对关联数组(Support for keys in list)进行数组破坏:

<?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可能不再了解变量的类型,因此您需要添加一些@var Type PHPDocs以维护自动完成功能
  • 不适用于重构工具。例如,如果您重命名属性之一,则数组销毁部分也不会自动重命名。

因此,我建议您以常规方式进行操作:

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

请勿使用extract

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

  • 这可能会导致安全问题。即使您谨慎操作,也可能导致将来出现明显的安全漏洞。如果您确实要使用它,请不要将其与用户输入(例如$_GET$_POST)一起使用,除非您想成为一个恶意的黑客时代。
  • 可能导致难以发现的错误
  • 如果类或数组将来会发生变化,则通过引入新属性,如果它与已使用的变量重合,则它可能会破坏您的代码,除非您使用EXTR_SKIP标志或类似标志

答案 2 :(得分:0)

变量变量是一种可以做到这一点的方法。 foreach使您保持在范围内,因此您可以从数组中明确定义变量,如下所示:

$args = ['a' => 1, 'b' => 2, 'c' => 3];
foreach (['a', 'c'] as $v) $$v = $args[$v];
// $a is 1, $b is undefined, $c is 3

它真的不漂亮,幸好这已经在https://wiki.php.net/rfc/short_list_syntax的7.1中得到了解决。这可以让你在上面的例子中说['a' => $a, 'c' => $c] = $args;

由于7.1包含了一种为你的var使用与assoc数组键不同的名称的方法,所以我在这里也提到了使用我的方法这很简单。

foreach (['a' => 'eh', 'b' => 'bee'] as $k => v) $$v = $args[$k];
// $eh is 1, $bee is 2