Forum Moderators: coopster

Message Too Old, No Replies

foreach repeating second to last value, omiting last

         

natbur

8:32 pm on Jun 10, 2007 (gmt 0)

10+ Year Member



My site is running PHP5 and I'm getting some weird behavior from my foreach loop.

I have a form that users fill in data into text boxes and submit. An array is created from the text boxes(the print_r is below):

Array (
[TextBox1] => Array ( [name] => TextBox1 [value] => ...someText... [show] => 1 [required] => 1 [text] => ...enteredText1...)
[TextBox2] => Array ( [name] => TextBox2 [value] => ...someMoreText... [show] => 1 [required] => 1 [text] => ...enteredText2...)
[TextBox3] => Array ( [name] => TextBox3 [value] => ...evenMoreText... [show] => 1 [required] => 1 [text] => ...enteredText3...)
[TextBox4] => Array ( [name] => TextBox4 [value] => ...LastBitOfText... [show] => 1 [required] => 1 [text] => ...enteredText4...)
)

The loop that processes this array is:

foreach($TextBoxData as $text)
{
if($text['text']!= "")
{
$msg .= "- In Response to: \n";
$msg .= " ".filter_text($text['value'], "nohtml")." \n";
$msg .= " - They said: \n";
$msg .= " ".filter_text($text['text'], "nohtml")." \n";
$msg .= "\n";
}
}

the output i get is:
-In Resonse to:
...someText...
-They said:
...enteredText1...

-In Resonse to:
...someMoreText...
-They said:
...enteredText2...

-In Resonse to:
...evenMoreText...
-They said:
...enteredText3...

-In Resonse to:
...evenMoreText...
-They said:
...enteredText3...

It repeats the second to last, and omits the last completely.
if i change the loop to:

 foreach($TextBoxData as &$text)

everything works correctly. I see this as a band-aid, and don't understand why I need to pass my array as a reference to get it to work. Also, I'd like to make this so that others can use this script as well, but PHP4 throws an error if you try to pass by reference in a foreach loop.

eelixduppy

8:48 pm on Jun 10, 2007 (gmt 0)



Welcome to WebmasterWorld

This has been reported as a bug [bugs.php.net] and found to be expected behavior. Refer to that page for more information. I have to say that I do not like it this behavior; never ran into it, though.

good luck

natbur

9:01 pm on Jun 10, 2007 (gmt 0)

10+ Year Member



blast, that's not what I wanted to hear...I suppose knowing I didn't do something wrong is of some comfort.

natbur

9:11 pm on Jun 10, 2007 (gmt 0)

10+ Year Member



the page you pointed me to talks about problems when you call the foreach by reference, this is exactly what I'm trying to avoid. When I don't call the foreach by reference, I get the behavior I've described.

However, unsetting the value immediately after each foreach() exited corrected the problem.

[edited by: natbur at 9:20 pm (utc) on June 10, 2007]

eelixduppy

9:14 pm on Jun 10, 2007 (gmt 0)



hehe...oops. Looks like I reversed it there. I'm going to test your problem in about 30 seconds. If you are willing to wait that long, I'll get back to you :)

[edit reason]changed from minutes to seconds ;)[/edit]

[edited by: eelixduppy at 9:23 pm (utc) on June 10, 2007]

eelixduppy

9:22 pm on Jun 10, 2007 (gmt 0)



OK, well, I'm glad you figured out a solution by unsetting the value. Which value is that, by the way?

And just out of curiosity, does the following code produce the same results, because it is working fine on my machine:


$array = array(
'TextBox1' => array('value' => 'someText1','text' => '...enteredText1...'),
'TextBox2' => array('value' => 'someText2','text' => '...enteredText2...'),
'TextBox3' => array('value' => 'someText3','text' => '...enteredText3...'),
'TextBox4' => array('value' => 'someText4','text' => '...enteredText4...')
);
#
$msg = '';
foreach($array as $text)
{
if($text['text']!= "")
{
$msg .= "- In Response to: \n";
$msg .= " ".$text['value']." \n<br>";
$msg .= " - They said: \n";
$msg .= " ".$text['text']." \n<br>";
$msg .= "<br>\n";
}
}
echo $msg;

natbur

9:32 pm on Jun 10, 2007 (gmt 0)

10+ Year Member



further up the page, i'd parsed through the array to check for missing fields with

foreach($TextBoxData as &$text)
{
if($text['required'] == 1 && $text['text'] == "")
{
$text['missing'] = 1;
$missing++;
}
}
unset($text);

Adding that unset fixed the problem(It's always fun finding problems a couple hundred lines further up...). It's strange that PHP scope doesn't destroy the $text variable as soon as the foreach exits.

I thought perhaps it was an internal pointer issue, so I tried resetting the array just prior to the loop, but that doesn't fix it. For now, I'll just make a habbit of unsetting the temp variable after each foreach loop that I call with a reference.

eelixduppy

10:18 pm on Jun 10, 2007 (gmt 0)



Cool. That makes sense then if $text is a reference. So I guess in the end that "bug" report was addressing the problem :)

natbur

10:33 pm on Jun 10, 2007 (gmt 0)

10+ Year Member



Yeah, I just didn't seem that it was being caused from above, because the array was correct right before it's printed. I could do a print_r right before running the foreach, and the array was still correct. Odd that.