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

Cot*_*ten 23 php destructuring

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

obj = {keyA: 'Hello from A', keyB: 'Hello from B'}
{keyA, keyB} = obj
Run Code Online (Sandbox Code Playgroud)

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

$info = array('coffee', 'brown', 'caffeine');
list($drink, $color, $power) = $info;
Run Code Online (Sandbox Code Playgroud)

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

thp*_*hpl 34

对于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"
Run Code Online (Sandbox Code Playgroud)

提取对象

提取对象的工作方式几乎相同.由于extract只将数组作为参数,我们需要将对象属性作为数组.get_object_vars为你这样做.它返回一个关联数组,其中所有公共属性都是键,其值是值.

<?php

class User {

    public $name = 'Thomas';

}

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

var_dump($name); // string(6) "Thomas"
Run Code Online (Sandbox Code Playgroud)

陷阱

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

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

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

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

您现在可以在list()或其新的速记[]语法中指定键.这使得能够使用非整数或非顺序密钥对数组进行解构.- http://php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring

现在可以使用简写数组语法([])来解析分配的数组(包括在foreach中),作为现有list()语法的替代,仍然支持该语法.- http://php.net/manual/en/migration71.new-features.php#migration71.new-features.support-for-keys-in-list

例如:

$test_arr = ['a' => 1, 'b' => 2];
list('a' => $a, 'b' => $b) = $test_arr;
var_dump($a);
var_dump($b);
Run Code Online (Sandbox Code Playgroud)

从7.1.0开始输出以下内容

int(1) 
int(2)
Run Code Online (Sandbox Code Playgroud)

  • 从 PHP 7.1 开始,使用两种格式之一进行解构。list() 现在支持显式索引,可以是字符串 http://php.net/manual/en/migration71.new-features.php#migration71.new-features.support-for-keys-in-list 并且有使用方括号的列表简写 http://php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring (3认同)
  • 从 php &gt;= 7.2 开始,你可以这样做,`['a' =&gt; $a, 'b' =&gt; $b] = ['a' =&gt; 1, 'b' =&gt; 2]`。 (2认同)

Yah*_*din 33

我注意到接受的答案遗漏了使用简写符号的示例、使用提取的安全问题和 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
Run Code Online (Sandbox Code Playgroud)

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

关联数组解构 (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
Run Code Online (Sandbox Code Playgroud)

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

对象解构 (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)
Run Code Online (Sandbox Code Playgroud)

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

  • IDE 可能不再理解变量的类型,因此您需要添加一些@var TypePHPDoc 以维护自动完成功能
  • 不适用于重构工具。例如,如果您重命名其中一个属性,则数组解构部分也不会自动重命名。

因此,我建议您按照正常方式进行操作:

$id = $user->id
$name = $user->firstName
Run Code Online (Sandbox Code Playgroud)

不使用 extract

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

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

  • 作为后续,[提取有什么问题](/sf/ask/58058521/):它可以将未经消毒的未知变量放入全局(或本地函数)命名空间,或覆盖您自己的变量。它还可能导致其他程序员想知道以这种方式引入的变量在哪里发挥作用。基本上,只有在确定输入的数据安全并且您了解可能引入的所有变量时才明智地使用。谨慎使用用户数据。 (2认同)