Modify array values in foreach loop

120,809

Solution 1

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.

Solution 2

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.

Share:
120,809
Garbit
Author by

Garbit

Bio I'm a UX Researcher and Software Engineer at Samsung AI Center - Cambridge. I explore Human-Centric AI through the design of wellbeing technologies that promote a deeper understanding of ourselves using computer vision, ubiquitous sensing, and personal data. I am an experienced full-stack developer with a keen interest in designing compelling user experiences and developing innovative products for both mobile and web. I lead products from design concepts to full implementation working alongside engineers, designers, and researchers to realise next generation technologies. I have a background in both Software Engineering and UX Research and thoroughly enjoy designing and developing civic technology that empowers and connects people through web and mobile platforms. Find our more on my portfolio site http://andygarbett.co.uk Dev Projects https://App-Movement.com a platform for communities to commission and automatically generate their own mobile apps around the real world issues that they face. http://Feed-Finder.co.uk, a mobile app that allows breastfeeding mothers to rate and review suitable breastfeeding locations. http://irismsg.io, a distributed SMS donation platform that enables individuals to donate SMS credit to solidarity groups in Greece. http://Sleepful.me, a social network to deliver cognitive behavioural therapy to those with insomnia and severe sleep disorders. http://Fearsquare.com, a Foursquare &amp; UK Police data mashup that creates a personal crime exposure history from your Foursquare checkin data. http://collectionsdivetwmuseums.org.uk, a novel discovery interface for online heritage collections created in partnership with Tyne and Wear Archives and Museums and Microsoft Research Cambridge.

Updated on March 03, 2021

Comments

  • Garbit
    Garbit about 3 years

    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']);
    }
    
  • Garbit
    Garbit about 12 years
    Nice! so the & sign will pass by reference? is that the correct terminology?
  • jemcmorrow
    jemcmorrow about 12 years
    you are missing part with passing entire $question variable into get_answers_by_question_id()
  • Rene Pot
    Rene Pot about 12 years
    @ArtjomKurapov what do you mean? What part
  • Paystey
    Paystey about 12 years
    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.
  • jemcmorrow
    jemcmorrow about 12 years
    @Topener well he needs $question to be updated inside get_answers_by_question_id.. and you are just passing its id
  • Rene Pot
    Rene Pot about 12 years
    @ArtjomKurapov I think either you or me misunderstood the question. Thats not what I see he asked
  • jemcmorrow
    jemcmorrow about 12 years
    @Topener right.. I thought get_answers_by_question_id does more than just fetch data from DB and actually changes $question inside too
  • Garbit
    Garbit about 12 years
    I've found that both methods above work however considering what @Paystey has said I've used the Key Value pair type loop instead of the by reference, it seems messy having the use unset($question) after the loop
  • Hippyjim
    Hippyjim over 10 years
    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.
  • Nico
    Nico over 8 years
    @Paystey can you cite your sources or give a detailed explaination ?
  • Kalzem
    Kalzem about 8 years
    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.
  • Sz.
    Sz. about 7 years
    @BabyAzerty: Paystey didn't say references "in general", but in foreach, regarding horror like this: stackoverflow.com/questions/3307409/… (@Nico, FYI, too.)
  • benjaminhull
    benjaminhull over 5 years
    Much more intuitive than doing a foreach - this is exactly what this function is designed for.
  • COil
    COil over 2 years
    Except that you don't have access to the key.