PHP-在foreach循环中修改当前对象


110

我想知道是否可以编辑foreach循环中正在处理的当前对象

我正在处理一系列对象$questions,我想遍历数据库中查找与该问题对象相关的答案。因此,对于每一个问题去获取答案对象,并更新当前$question 里面我的foreach循环,这样我可以输出/别处过程。

foreach($questions as $question){
    $question['answers'] = $answers_model->get_answers_by_question_id($question['question_id']);
}

正如ArtjomKurapov和@topener所建议的那样,我正在使用&符号查找“按引用传递”。谢谢小伙:)

Answers:


206

有两种方法

foreach($questions as $key => $question){
    $questions[$key]['answers'] = $answers_model->get_answers_by_question_id($question['question_id']);
}

这样可以保存密钥,因此您可以在主$questions变量中再次对其进行更新

要么

foreach($questions as &$question){

添加&会保持$questions更新。但我想说,尽管推荐的时间较短,但还是建议使用第一个(请参阅Paystey的评论)

根据PHP foreach文档

为了能够直接在循环内修改数组元素,在$ value之前加&。在这种情况下,该值将通过引用分配。


32
foreach确实不建议使用in引用foreach,因为循环值部分的传递会导致不可预测的行为。它可能会更长,但是使用此处的方法1会更加安全。
Paystey

1
我只是花了一个困惑的小时来调试由在foreach中使用引用引起的问题。我在第二次foreach调用中重复使用了相同的变量名-当我通过引用传递了第一个时,它一直在修改数组中的最后一项!使用显式索引不会有这个问题。
Hippyjim 2014年

7
@Paystey您可以引用您的消息来源或提供详细说明吗?
Nico 2015年

2
为什么操纵引用不安全?在C / C ++中您必须在各处操纵引用是否不安全?安全与否取决于语言,而不是语言。
Kalzem '16

2
@BabyAzerty:Paystey并未“一般性”地提及参考文献,而是在foreach,关于这样的恐怖:stackoverflow.com/questions/3307409/…(@ Nico,FYI也是如此)
Sz。

6

一定array_map要使用容器实现ArrayAccess来派生对象)只是一种更聪明的语义方式来做到这一点?

我所看到的大多数语言和实现中的数组映射语义都相似。它旨在根据输入数组元素返回修改后的数组(高级忽略语言编译/运行时类型首选项);循环意味着执行更多的逻辑。

为了通过ID / PK检索对象,具体取决于您是否使用SQL(似乎建议使用),我将使用过滤器以确保获得有效PK的数组,然后使用逗号爆破并放入SQL IN()子句中返回结果集。它通过SQL进行一次调用而不是多次调用,从而优化了call->wait周期的一部分。最重要的是,我的代码对于具有某种能力的任何语言的人都可以很好地理解,并且我们不会遇到可变性问题。

<?php

$arr = [0,1,2,3,4];
$arr2 = array_map(function($value) { return is_int($value) ? $value*2 : $value; }, $arr);
var_dump($arr);
var_dump($arr2);

<?php

$arr = [0,1,2,3,4];
foreach($arr as $i => $item) {
    $arr[$i] = is_int($item) ? $item * 2 : $item;
}
var_dump($arr);

如果您知道自己在做什么,就永远不会有变异性问题(如果要覆盖,请牢记,您$arr始终$arr = array_map可以保持明确。


2
比执行foreach更加直观-这正是此功能的目的所在。
benjaminhull
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.