PHP foreach更改原始数组值[重复]

Posted

技术标签:

【中文标题】PHP foreach更改原始数组值[重复]【英文标题】:PHP foreach change original array values [duplicate] 【发布时间】: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 文档中阅读:php.net/manual/en/control-structures.foreach.php 【参考方案1】:

使用&amp;:

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

unset($value);

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

PHP documentation for Passing by Reference

编辑 2018

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

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

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

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

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

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

    代码可读性。 在 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,所以不知道有任何更新

以上是关于PHP foreach更改原始数组值[重复]的主要内容,如果未能解决你的问题,请参考以下文章

PHP中有没有办法在foreach中重新启动循环,或者在开关中更改测试值?

PHP:替换数组值不会在 foreach 循环后保留

用于逗号分隔值的PHP'foreach'[重复]

我在 forEach 中更新的变量,返回到它们的原始值 [重复]

reduce 的用法,个人感觉比for、foreach 都要好用,用法比较简洁

PHP未设置嵌套数组的部分