首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在php中解构对象/关联数组的赋值

在php中解构对象/关联数组的赋值
EN

Stack Overflow用户
提问于 2015-01-30 17:36:15
回答 3查看 35K关注 0票数 50

在CoffeeScript,Clojure,ES6和许多其他语言中,我们有对象/地图/等等的解构,有点像这样:

代码语言:javascript
复制
obj = {keyA: 'Hello from A', keyB: 'Hello from B'}
{keyA, keyB} = obj

我在php中找到了list function,它可以让你像这样解构数组:

代码语言:javascript
复制
$info = array('coffee', 'brown', 'caffeine');
list($drink, $color, $power) = $info;

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-30 18:09:51

对于PHP7.0及更低版本,这超出了list的功能范围。文档状态:

列表仅适用于数值数组,并假定数值索引从0开始。

其中一个适合您的功能是extract()函数,它将变量从数组导入到当前符号表中。虽然使用list可以显式地定义变量名,但extract()不能给您这种自由。

提取关联数组

使用extract,您可以这样做:

代码语言:javascript
复制
<?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为您做到了这一点。它返回一个关联数组,将所有公共属性作为键,并将它们的值作为值。

代码语言:javascript
复制
<?php

class User {

    public $name = 'Thomas';

}

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

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

陷阱

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

  • list是一种语言构造,而extract()
  • 可能会覆盖预先定义的变量,而数组键作为变量名可能是无效的

通过可以作为第二个参数传递给extract()$flags参数,您可以在变量冲突或无效的情况下影响行为。但是,了解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中),作为现有列表()语法的替代,该语法仍然受支持。

例如:

代码语言:javascript
复制
$test_arr = ['a' => 1, 'b' => 2];
list('a' => $a, 'b' => $b) = $test_arr;
var_dump($a);
var_dump($b);

将从7.1.0开始输出以下内容

代码语言:javascript
复制
int(1) 
int(2)
票数 64
EN

Stack Overflow用户

发布于 2019-08-02 22:14:38

我注意到,公认的答案遗漏了使用速记符号的示例,使用extract的安全问题,以及IDE问题。

数值数组解构(PHP 7.1)

PHP7.1开始支持数值数组解构(Symetric array destructuring),如下所示:

代码语言:javascript
复制
<?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):

代码语言:javascript
复制
<?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将对象转换为关联数组,然后使用关联数组解构。

代码语言:javascript
复制
<?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时注意到的一些问题:

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

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

代码语言:javascript
复制
$id = $user->id
$name = $user->firstName

不要使用extract

使用extract时,所有变量都会被设置。使用它是一个非常糟糕的想法,因为:

  • 它可能会导致安全问题。即使你很小心,它也可能在将来导致不明显的安全漏洞。如果您确实使用了
  • ,请不要将其与用户输入(例如$_GET$_POST)一起使用,除非您想让恶意黑客大行其道。如果将来类或数组发生更改,通过引入新属性,除非您使用
  • 标志或类似的

,否则它可能会破坏您的代码

票数 39
EN

Stack Overflow用户

发布于 2017-01-06 04:36:58

变量是实现这一目标的一种方法:

代码语言:javascript
复制
$args = ['a' => 1, 'b' => 2, 'c' => 3];
foreach (['a', 'c'] as $v) $$v = $args[$v];
// $a is 1, $b is undefined, $c is 3

这真的不是很好,谢天谢地,在7.1版本中,https://wiki.php.net/rfc/short_list_syntax已经解决了这个问题。这将允许您在上面的示例中使用['a' => $a, 'c' => $c] = $args;

因为7.1提供了一种方法,可以为您的var使用不同于assoc数组键的名称。在这里使用变量变量也是非常简单的:

代码语言:javascript
复制
foreach (['a' => 'eh', 'b' => 'bee'] as $k => $v) $$v = $args[$k];
// $eh is 1, $bee is 2

一些开发人员和一些编码风格将$$var定义为类似于直接使用evalextractGPR神奇变量的反模式。这是因为使用变量会使代码更难理解,这会直接导致错误,并阻止静态代码分析工具发挥作用。

如果您确实采用了$$var,那么改用${$var}表单会很有帮助,这显然表明作者并没有简单地键入过多的$s,并且在审计代码时可以避免作者立即得到负面反馈。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28232945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档