【问题标题】:PHP foreach change original array values [duplicate]PHP foreach更改原始数组值[重复]
【发布时间】:2013-02-08 02:19:09
【问题描述】:

我是多维数组的新手,这让我很烦恼。

我的数组如下:

$fields = array(
    "names" => array(
         "type"         => "text",
         "class"        => "name",
         "name"         => "name",
         "text_before"  => "name",
         "value"        => "",
         "required"     => true,
    )
)

然后我有一个函数检查这些输入是否被填写,如果需要的话。

function checkForm($fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

现在我的问题是这一行

$fields[$field]['value'] = "Some error";

我想更改原始数组的内容,因为我要返回它,但是如何在我的 foreach 循环中获取当前数组的名称(本例中的名称)?

【问题讨论】:

标签: php arrays foreach


【解决方案1】:

使用&amp;:

foreach($arr as &$value) {
    $value = $newVal;
}
unset($value);

&amp; 将数组的值作为引用传递,并且不会创建变量的新实例。因此,如果您更改引用,原始值将会改变。

PHP documentation for Passing by Reference

编辑 2018

这个答案似乎受到互联网上很多人的青睐,这就是为什么我决定添加更多信息和警告。
虽然foreach(或函数)中的传递引用是一种简洁而简短的解决方案,但对于许多初学者来说,这可能是一个危险的陷阱。

  1. PHP 中的循环没有自己的作用域。 - @Mark Amery

    当变量在同一范围内重复使用时,这可能是一个严重的问题。 Another SO question nicely illustrates why that might be a problem.

  2. 至于 foreach 依赖于 PHP 5 中的内部数组指针,改变它 在循环内可能会导致意外的行为。 - foreach 的 PHP 文档。

    在同一循环的迭代期间取消设置记录或更改哈希值(键)可能会导致 PHP

  3. Foreach 表演。
    通常,由于写时复制功能,PHP 更喜欢按值传递。这意味着 PHP 在内部不会创建重复数据,除非它的副本需要更改。 foreach 中的按引用传递是否会提供任何性能改进是值得商榷的。与往常一样,您需要测试您的特定场景并确定哪个选项使用更少的内存和 CPU 时间。有关详细信息,请参阅 NikiC 下面链接的 SO 帖子。

  4. 代码可读性。
    在 PHP 中创建引用很快就会失控。如果您是新手并且无法完全控制自己在做什么,最好远离参考。有关&amp; 操作员的更多信息,请查看本指南:Reference — What does this symbol mean in PHP?
    想进一步了解这部分 PHP 语言的朋友:PHP References Explained

@NikiC 对 PHP foreach 循环内部逻辑的一个非常好的技术解释:
How does PHP 'foreach' actually work?

【讨论】:

  • 除了列出的问题之外,我建议在foreach 右括号之后添加unset($value);,以确保在迭代后引用变量不再可用。 3v4l.org/2V2AQ
【解决方案2】:

In PHP, passing by reference (&amp;) is ... controversial. I recommend not using it unless you know why you need it and test the results.

我建议您执行以下操作:

foreach ($fields as $key => $field) {
    if ($field['required'] && strlen($_POST[$field['name']]) <= 0) {
        $fields[$key]['value'] = "Some error";
    }
}

所以基本上在需要值时使用$field,在需要更改数据时使用$fields[$key]

【讨论】:

  • 很好,这行得通!首先尝试过这样的事情,但我想我搞砸了一些地方:) 现在我将使用你的例子一千次,永远不会忘记! :)
  • 很高兴它有帮助。另外,我建议阅读我链接的文章,以及 foreach 的官方文档(php.net/manual/ro/control-structures.foreach.php
  • 底线:如果您要更改数组/变量 - 那么您应该使用参考。它更快、更干净、更易读。
  • 我很好奇为什么在foreach 中通过引用传递应该是有争议的?这不像是一个带有隐藏副作用或任何东西的函数调用。
  • 感谢您说“通过引用传递 (&) 是……有争议的”,而不是“不要通过引用传递”或“通过引用传递是邪恶的”。不太可能引发一场火焰战争。 :)
【解决方案3】:
function checkForm(& $fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

这是我建议通过引用传递的内容

【讨论】:

  • 该技术用于改变原始变量的值。因为 PHP 支持按值传递技术。我们需要在变量前面添加 '&' 字符来说明要通过引用传递的值
  • 那为什么还要返回$fields
  • 这是建议的 3 个中最差的答案。对于任何偶然发现此答案的人,请不要设计您的函数来更改数据并返回它。对于原作者:您没有提供任何解释为什么这个解决方案会比其他解决方案更好,或者它是如何工作的......
【解决方案4】:

试试这个

function checkForm($fields){
        foreach($fields as $field){
            if($field['required'] && strlen($_POST[$field['name']]) <= 0){
                $field['value'] = "Some error";
            }
        }
        return $field;
    }

【讨论】:

  • 不要这样做。我可以看到您的代码至少有两点错误:分配给 $field 不起作用(这样做时 $fields 数组永远不会被修改),并且 return $field 返回单个字段,而不是数组。
【解决方案5】:

使用foreach($fields as &amp;$field){ - 这样您就可以使用原始数组。

Here 更多的是通过引用传递。

【讨论】:

  • @RBA 请参考上面的答案 - 他们有更多的细节和更新 - 我有一段时间没有使用 php,所以不知道有任何更新
猜你喜欢
  • 1970-01-01
  • 2014-11-08
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
相关资源
最近更新 更多