PHP foreach更改原始数组值


143

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

我的数组如下:

$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循环中获取当前数组的名称(此示例中的名称)?



1
无论您是什么新人(或曾经是新人),您都可以从PHP文档中读取以下内容:php.net/manual/en/control-structures.foreach.php
Nikolay Ivanov,

Answers:


261

在PHP中,通过引用(&)传递是有争议的。我建议不要使用它,除非您知道为什么需要它并测试结果。

我建议您执行以下操作:

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

因此,基本上$field在需要值和$fields[$key]需要更改数据时使用。


很好,这可行!首先尝试过类似的方法,但我想我搞砸了一些地方:)现在,我将使用您的示例一千次,永远不会忘记!:)
Jeppe

很高兴它有所帮助。另外,我建议阅读我联系的文章,也为的foreach(官方文档php.net/manual/ro/control-structures.foreach.php
弗拉德普雷达

4
底线:如果要更改数组/变量,则应使用引用。它更快,更清洁且更具可读性。
露露

2
我很好奇为什么在a中引用引用foreach会引起争议?这不像是带有隐藏副作用或其他任何东西的函数调用。
UncaAlby

1
感谢您说“通过引用(&)引起争议...”而不是“不通过引用”或“通过引用是邪恶的”。发动火焰战争的可能性较小。:)
肖恩·比恩

162

用途&

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

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

http://php.net/manual/en/language.references.pass.php

Edit 2018
这个答案似乎在互联网上受到很多人的青睐,这就是为什么我决定添加更多信息和谨慎的词。
尽管在foreach(或函数)中通过引用传递是一个干净而简短的解决方案,但对于许多初学者而言,这可能是一个危险的陷阱。

  1. PHP中的循环没有自己的作用域。-@马克·阿默里

    当在相同范围内重用变量时,这可能是一个严重的问题。另一个SO问题很好地说明了为什么这可能是一个问题。

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

    在同一循环中的迭代过程中,取消记录设置或更改哈希值(键)可能会导致PHP <7中潜在的意外行为。当数组本身是引用时,此问题会变得更加复杂。

  3. Foreach性能。
    通常,由于写时复制功能,PHP倾向于按值传递。这意味着PHP内部不会创建重复数据,除非需要更改其副本。是否值得一提的是通过引用传递是否foreach可以提高性能。通常情况下,您需要测试您的特定方案并确定哪个选项使用更少的内存和CPU时间。有关更多信息,请参见下面由NikiC链接的SO帖子。

  4. 代码可读性。
    在PHP中创建引用很快就会失去控制。如果您是新手,并且无法完全控制自己的工作,则最好远离引用。有关&运算符的更多信息,请参阅本指南:参考-这个符号在PHP中是什么意思?
    对于那些想进一步了解PHP语言这一部分的人:PHP参考说明

@NikiC对PHP foreach循环的内部逻辑做了很好的技术解释:PHP'foreach
'实际上是如何工作的?


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

15

使用foreach($fields as &$field){-因此您将使用原始数组。

是有关通过引用传递的更多信息。


@RBA请参考上面的答案-他们有更多详细信息和更新-我已经有一段时间没有使用php了,所以对此
一无所知

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

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


该技术用于更改原始变量的值。因为PHP支持按值传递技术。我们需要添加“&”字符变量状态前该值通过引用传递
萨加尔噶当派

1
那为什么还回来$fields呢?
MAZux

这是建议的3中最差的答案。对于偶然发现此答案的人,请勿设计您的函数来更改数据并返回。对于原始作者:您没有提供任何解释为什么这种解决方案比其他解决方案更好,或者它是如何工作的
。– Dharman

-6

试试这个

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

3
不要这样做。我可以看到至少有两件事与您的代码有误:分配给$ field不起作用(执行此操作时永远不会修改$ fields数组),并返回$ field返回单数字段,而不是数组。
Staplerfahrer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.