146

I was wondering if it is possible to edit the current object that's being handled within a foreach loop

I'm working with an array of objects $questions and I want to go through and look for the answers associated with that question object in my db. So for each question go fetch the answer objects and update the current $question inside my foreach loop so I can output/process elsewhere.

foreach($questions as $question){
    $question['answers'] = $answers_model->get_answers_by_question_id($question['question_id']);
}
1
  • As both ArtjomKurapov and @topener suggested I was looking for 'pass by reference' using the & sign. Thanks chaps :) have a nice day
    – Garbit
    Commented Apr 12, 2012 at 10:12

2 Answers 2

273

There are 2 ways of doing this

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

This way you save the key, so you can update it again in the main $questions variable

or

foreach($questions as &$question){

Adding the & will keep the $questions updated. But I would say the first one is recommended even though this is shorter (see comment by Paystey)

Per the PHP foreach documentation:

In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.

12
  • 43
    References in foreach is really not recommended, the way the foreach passes around the value part of the loop results in unpredicatble behaviour. It may be longer but you're far safer using method 1 here.
    – Paystey
    Commented Apr 12, 2012 at 10:11
  • 4
    I just spent a perplexed hour debugging an issue caused by using a reference in a foreach. I re-used the same variable name for a second foreach call - as I'd passed the first by reference, it kept modifying the last item in the array! Using an explicit index wouldn't have had this problem.
    – Hippyjim
    Commented Jan 24, 2014 at 10:03
  • 10
    @Paystey can you cite your sources or give a detailed explaination ?
    – Nico
    Commented Oct 8, 2015 at 14:22
  • 3
    Why would manipulating references be unsafe? Is C/C++ where you have to manipulate references everywhere unsafe? It's up to you to make it safe or not, not the language.
    – Kalzem
    Commented Feb 14, 2016 at 14:41
  • 5
    @BabyAzerty: Paystey didn't say references "in general", but in foreach, regarding horror like this: stackoverflow.com/questions/3307409/… (@Nico, FYI, too.)
    – Sz.
    Commented Feb 19, 2017 at 13:11
10

Surely using array_map and if using a container implementing ArrayAccess to derive objects is just a smarter, semantic way to go about this?

Array map semantics are similar across most languages and implementations that I've seen. It's designed to return a modified array based upon input array element (high level ignoring language compile/runtime type preference); a loop is meant to perform more logic.

For retrieving objects by ID / PK, depending upon if you are using SQL or not (it seems suggested), I'd use a filter to ensure I get an array of valid PK's, then implode with comma and place into an SQL IN() clause to return the result-set. It makes one call instead of several via SQL, optimising a bit of the call->wait cycle. Most importantly my code would read well to someone from any language with a degree of competence and we don't run into mutability problems.

<?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);

vs

<?php

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

If you know what you are doing will never have mutability problems (bearing in mind if you intend upon overwriting $arr you could always $arr = array_map and be explicit.

2
  • 2
    Much more intuitive than doing a foreach - this is exactly what this function is designed for. Commented Nov 20, 2018 at 12:54
  • Except that you don't have access to the key.
    – COil
    Commented Sep 16, 2021 at 17:19

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.