SSISO Community

시소당

제어구조 - foreach

foreach
PHP  4(PHP  3는  아님)는  펄이나  다른  언어와  같이  foreach구문을  지원합니다.  이런  구문은  간단하게  배열에  대한  작업을  수행하는  가장  쉬운  기법입니다.  foreach는  배열에서만  작동하고  다른  데이터형을  갖는  변수나  초기화되지  않은  변수에  대해서  이  구문을  사용하려한다면  에러  메시지를  만날것입니다.  이  구문은  두가지  문법이  있습니다;  두번째보다는  첫번째문법이  더  유용한  사용법입니다:  


foreach  (array_expression  as  $value)  statement
foreach  (array_expression  as  $key  =>  $value)  statement
  



첫번째  형태는  array_expression에서  주어진  배열에  대해  루프를  돈다.  각  루프에서  현재  배열요소(element)의  값은  $value  로  지정되고  내부적인  배열  포인터는  하나씩  이동하게  된다  (그래서  다음  루프에서  다음  배열  요소를  보게  될것이다)  

두번째  루프도  같은  일을  한다.  단  현재  배열요소의  키(key)값은  각  루프의  $key변수로  지정된다.  


참고:  foreach문이  처음  실행할때,  내부적인  배열  포인터는  자동적으로  배열의  첫번째  요소(element)로  리셋된다.  따라서  foreach절  이전에  reset()함수를  호출할  필요는  없다.  



참고:  foreach는  특정  배열의  복사본에  작용하는것이며  배열  자체를  직접  건드리지  않는다.  따라서,  배열  포인터는  each()함수  에  의해  변경이  되는것이  아니다.  넘어온  배열요소에  대한  변화는  원래  배열에는  영향을  주지  않는다.  하지만,  원래  배열의  내부적  포인터는  배열  처리에  의해  이동한다.  foreach루프는  완료될때까지  루프를  돌고,  배열의  내부적  포인터는  배열  끝을  가리키게된다.  



참고:  foreach는  '@'를  사용해서  에러메시지를  출력하지  못하도록  할수는  없다.  


다음  예는  기능적으로  동일하다는것을  알  필요가  있다:  


<?php
$arr  =  array("one",  "two",  "three");
reset  ($arr);
while  (list(,  $value)  =  each  ($arr))  {
      echo  "Value:  $value<br  />\n";
}

foreach  ($arr  as  $value)  {
      echo  "Value:  $value<br  />\n";
}
?>    


다음  예도  기능적으로  동일하다:  

<?php
$arr  =  array("one",  "two",  "three");
reset  ($arr);
while  (list($key,  $value)  =  each  ($arr))  {
      echo  "Key:  $key;  Value:  $value<br  />\n";
}

foreach  ($arr  as  $key  =>  $value)  {
      echo  "Key:  $key;  Value:  $value<br  />\n";
}
?>    



더  많은  예제  코드들이  사용법에  대해서  설명해준다:  


<?php
/*  foreach  예제  1:  값만  */

$a  =  array(1,  2,  3,  17);

foreach  ($a  as  $v)  {
      echo  "\$a의  현재  값:  $v.\n";
}

/*  foreach  예제  2:  값  (키는  가상으로  출력)  */

$a  =  array(1,  2,  3,  17);

$i  =  0;  /*  가상  목적으로만  사용  */

foreach  ($a  as  $v)  {
      echo  "\$a[$i]  =>  $v.\n";
      $i++;
}

/*  foreach  예제  3:  키와  값  */

$a  =  array(
      "one"  =>  1,
      "two"  =>  2,
      "three"  =>  3,
      "seventeen"  =>  17
);

foreach  ($a  as  $k  =>  $v)  {
      echo  "\$a[$k]  =>  $v.\n";
}

/*  foreach  예제  4:  다차원  배열  */

$a[0][0]  =  "a";
$a[0][1]  =  "b";
$a[1][0]  =  "y";
$a[1][1]  =  "z";

foreach  ($a  as  $v1)  {
      foreach  ($v1  as  $v2)  {
              echo  "$v2\n";
      }
}

/*  foreach  예제  5:  동적  배열  */

foreach  (array(1,  2,  3,  4,  5)  as  $v)  {
      echo  "$v\n";
}
?>    






  add  a  note  User  Contributed  Notes
foreach  
barnacle83-phpnotes  at  yahoo  dot  com
30-Jun-2005  05:06  
Here  are  various  ways  I've  seen  to  iterate  arrays  by  reference  in  PHP4.
Based  on  my  tests,  I  have  placed  them  in  order  of  fastest  to  slowest.

Benchmarking  tool  I  used:
http://phplens.com/phpeverywhere/phpe-2004.htm#a3297
http://phplens.com/lens/dl/JPBS.zip

<?php
//  --------------------------------------------------------------------

foreach  (  array_keys($myArray)  as  $key  )  {
    $element  =&  $myArray[$key];
    ...
}

//  --------------------------------------------------------------------

foreach(  $myArray  as  $key  =>  $element  )  {
    $element  =&  $myArray[$key];
    ...
    unset($element);
}

//  --------------------------------------------------------------------

reset($myArray);
while  (  list($key)  =  each($myArray)  )  {
    $element  =&  $myArray[$key];
    ...
    unset($element);
}
?>

Andrew  
rokas3  at  gmail  dot  com
30-Jun-2005  04:52  
One  notice  that  foreach  has  strange  behaviour  with  copying  array.  It  sometimes  doubles  one  array  item.  For  example:

<?php
$array  =  array(
                          0  =>  array("one"  =>  "x",  "two"  =>  "y"),
                          1  =>  array("one"  =>  "z",  "two"  =>  "a"),
                          2  =>  array("one"  =>  "b",  "two"  =>  "c")
                          )

foreach  ($array  as  $item)  {
      echo  $item["one"]."  -  ".$item["two"]."<br  />";
}
/*
x  -  y
z  -  a
z  -  a
b  -  c
*/

This  can  be  avoided  with  reference:

foreach  ($array  as  &$item)  {
      echo  $item["one"]."  -  ".$item["two"]."<br  />";
}
/*
x  -  y
z  -  a
b  -  c
*/  
25-Jun-2005  07:00  
The  poster  who  submitted  this  loop  style  for  iterating  over  variables  by  reference:

<?php
foreach(  $object_list  as  $id  =>  $the_object  )  {
    $the_object  =  &$object_list[$id];  //  Re-assign  the  variable  to  point  to  the  real  object
    //  ...
    unset($the_object);  //  Break  the  link  to  the  object  so  that  foreach  doesn't  copy  the  next  one  on  top  of  it.
}
?>

Using  foreach()  means  you  end  up  making  a  copy  of  the  value,  and  then  quickly  reassign  it  to  be  a  reference.  This  is  a  waste  of  the  original  copy  operation.

You  may  want  to  consider  this,  more  meaningful  and  readable  alternative:

<?php

reset($object_list);

while  (list($key)  =  each($object_list))  {

      $the_object  =  &  $object_list[$key];  //  Re-assign  the  variable  to  point  to  the  real  object

      //  ...

      unset($the_object);  //  Break  the  link  to  the  object  so  that  foreach  doesn't  copy  the  next  one  on  top  of  it.

}
?>  
JaGx
18-Jun-2005  12:55  
On  the  note  of  Paul's  for  loop:
function  foo($x)  {
      global  $arr;  //  some  Array
      for($i=0;  $i  <  count($arr);  $i++)  {
          if($arr[$i][0]  ==  $x)  {
                  echo  $arr[$i][1]."\n";
                  foo($arr[$i][0]);
          }
      }
}

------------
The  middle  part  of  the  for  loop  is  evaluated  every  time  it  loops  which  means  the  count  function  is  called  as  many  times  as  it  loops.  It's  always  better  (performance/speed  wise)  to  put  the  count  as  the  initialization  code:

function  foo($x)  {
      global  $arr;  //  some  Array
      for($i=count($arr)-1;;  $i>=0;  $i++)  {
          if($arr[$i][0]  ==  $x)  {
                  echo  $arr[$i][1]."\n";
                  foo($arr[$i][0]);
          }
      }
}  
mike  at  invertedmind  dot  com
18-Jun-2005  03:24  
One  great  use  of  foreach  is  for  recursive  function  calls.    It  can  handle  things  that  would  otherwise  need  to  be  hand-coded  down  to  the  desired  level,  which  can  make  for  hard-to-follow  nesting.

<?
      /*
              May  you  never  be  forced  to  deal  with  a  structure
              like  this  in  real  life...
      */
      $items  =  array(
              -1,
              0,
              array(
                      array(1,2,3,4),
                      array(5,6,7,8),
                      array(9,10,11,12)
              ),
              array(
                      array("a",  "b",  "c"),
                      array("d",  "e",  "f"),
                      array("g",  "h",  "i")
              )
      );
      
      print_array($items,  0);
      
      function  print_array($arr,  $level)
      {
              $indent  =  str_repeat("&nbsp;",  $level  *  4);
              
              foreach  ($arr  as  $item)
              {
                      if  (is_array($item))
                      {
                              print  $indent  .  "Item  is  an  array...<br>\n";
                              print_array($item,  $level  +  1);
                      }
                      else
                              print  $indent  .  "Value  at  current  index:  "  .  $item  .  "<br>\n";
              }
      }
      
?>

This  will  output:

Value  at  current  index:  -1
Value  at  current  index:  0
Item  is  an  array...
      Item  is  an  array...
              Value  at  current  index:  1
              Value  at  current  index:  2
              Value  at  current  index:  3
              Value  at  current  index:  4
      Item  is  an  array...
              Value  at  current  index:  5
              Value  at  current  index:  6
              Value  at  current  index:  7
              Value  at  current  index:  8
      Item  is  an  array...
              Value  at  current  index:  9
              Value  at  current  index:  10
              Value  at  current  index:  11
              Value  at  current  index:  12
Item  is  an  array...
      Item  is  an  array...
              Value  at  current  index:  a
              Value  at  current  index:  b
              Value  at  current  index:  c
      Item  is  an  array...
              Value  at  current  index:  d
              Value  at  current  index:  e
              Value  at  current  index:  f
      Item  is  an  array...
              Value  at  current  index:  g
              Value  at  current  index:  h
              Value  at  current  index:  i

And  it  could  recurse  as  far  as  you  want  it  to  go.  
30-May-2005  02:17  
How  To  Use  References  In  Foreach  Safely  And  Sanely  In  PHP  4.

There  are  two  really  really  important  points  to  remember  about  foreach  and  references:
1.  foreach  makes  a  copy
2.  references  (and  unset!)  work  by  directly  manipulating  the  symbol  table

In  practice,  this  means  that  if  you  have  an  array  of  objects  (or  arrays)  and  you  need  to  work  on  them  *in-place*  in  a  foreach  loop,  you  have  to  do  this:

<?php
foreach(  $object_list  as  $id  =>  $the_object  )  {
      $the_object  =  &  $object_list[$id];  //  Re-assign  the  variable  to  point  to  the  real  object
      ....
      unset($the_object);  //  Break  the  link  to  the  object  so  that  foreach  doesn't  copy  the  next  one  on  top  of  it.
}
?>

This  really  works.  I  have  used  it  in  dozens  of  places.  Yes,  you  need  it  all,  including  the  unset().  You  will  get  extremely  hard-to-find  bugs  if  you  leave  out  the  unset().

Static.  
dave  at  davedelong  dot  com
29-May-2005  07:42  
A  "cheap"  way  to  sort  a  directory  list  is  like  so    (outputs  HTML,  one  indent  is  3  non-breaking  spaces):

<?php
function  echo_Dir($dir,  $level)  {
      //create  an  empty  array  to  store  the  directories:
      $dirs  =  array();
      //if  we  were  given  a  directory  to  list...
      if  (is_dir($dir))  {
              //and  if  we  can  open  it...
              if  ($handle  =  opendir($dir))  {
                      //change  directory:
                      chdir($dir);
                      //iterate  through  the  directory
                      while  (false  !==  ($file  =  readdir($handle)))  {  
                              if  ($file  !=  "."  &&  $file  !=  "..")  {  
                                      if  (is_dir($file))  {
                                              //only  add  legit  directories  to  the  array
                                              array_push($dirs,$file);
                                      }//end  if
                              }//end  if
                      }//end  while
                      //sort  the  array
                      sort($dirs);
                      //NOW  handle  each  directory  via  a  foreach  loop
                      foreach  ($dirs  as  $i  =>  $file)  {
                              $to_echo  =  str_repeat("\t",$level+1)  .  str_repeat("&nbsp;",$level*3)  .  $file  .  "<br>";
                              echo  $to_echo;
                              echo_Dir($file,$level+1);        
                      }//end  foreach
                      //return  to  the  parent  directory
                      chdir("../");
              }//end  if
              //close  the  handle
              closedir($handle);
      }//end  if
}//end  function
?>

For  an  example  of  what  this  outputs,  check  out  http://www.davedelong.com/php/echodir.php  
mark  at  myipower  dot  com
26-May-2005  11:10  
Here  is  a  solution  to  an  earlier  comment  I  found  that  worked  well  for  me.  It  only  goes  4  deep  on  a  complex  array  or  object  but  could  go  on  forever  I  would  imagine.

foreach($_SESSION  as  $value  =>  $lable1){
      echo  "The  elements  of  Value1  <B>"  .  $value  .  "</B>  is  <B>"  .  $lable1  .  "</B><br/>\n";
      if(is_array($lable1)  ||  is_object($lable1))  {
              foreach($lable1  as  $value2  =>  $lable2){
                      echo  "The  elements  of  Value2  <B>"  .  $value2  .  "</B>  is  <B>"  .  $lable2  .  "</B><br/>\n";
                      if(is_array($lable2)  ||  is_object($lable2))  {
                              foreach($lable2  as  $value3  =>  $lable3){
                                      echo  "The  elements  of  Value3  <B>"  .  $value3  .  "</B>is  <B>"  .  $lable3  .  "</B><br/>\n";
                                      if(is_array($lable3)  ||  is_object($lable3))  {
                                              foreach($lable3  as  $value4  =>  $lable4){
                                                      echo  "The  elements  of  Value4  <B>"  .  $value4  .  "</Bis  <B>"  .  $lable4  .  "</B>><br/>\n";
                                              }
                                      }
                              }
                      }
              }
              echo  "<br>";
      }
}  
flobee  at  gmail  dot  com
22-May-2005  05:32  
be  aware!  take  the  note  in  the  manual  serious:  "foreach  operates  on  a  copy  of  the  specified  array"
when  working  with  complex  systems  you  may  get  memory  problems  because  of  all  this  copies  of  arrays.

i  love  this  function  (easy  to  use)  and  use  it  more  often  than  "for"  or  "while"  functions  but  now  i  have  really  problems  on  this  and  finally  found  the  reason  (which  can  be  a  mess  to  find  out)!  
the  sum  of  memory  usage  sometimes  can  be  *2  than  you  really  need.  
flobee  at  gmail  dot  com
22-May-2005  05:31  
be  aware!  take  the  note  in  the  manual  serious:  "foreach  operates  on  a  copy  of  the  specified  array"
when  working  with  complex  systems  you  may  get  memory  problems  because  of  all  this  copies  of  arrays.

i  love  this  function  (easy  to  use)  and  use  it  more  often  than  "for"  or  "while"  functions  but  now  i  have  really  problems  on  this  and  finally  found  the  reason  (which  can  be  a  mess  to  find  out)!  
the  sum  of  memory  usage  sometimes  can  be  *2  than  you  really  need.  
wrm  at  metrushadows  dot  com
22-May-2005  02:10  
Another  example  for  printing  out  arrays.

<?php

$array  =  array(
1  =>  'milk',
2  =>  'eggs',
3  =>  'bread'
);

foreach  ($array  as  $array  =>  $value)  {
                      echo  "$value<br  />";
}

?>  
fred  at  flintstone  dot  com
21-May-2005  01:40  
<?
You  can  easily  use  FOREACH  to  show  all  POST  and  GET  variables  from  a  form  submission

function  showpost_and_get()
  {
    print  "<hr><h2>POST</h2><br>";
    foreach($_POST  as  $varName  =>  $value)  
    {  
      $dv=$value;
          $dv=$value;
          print  "Variable:  $varName  Value:  $dv<br>";  
      };

    print  "<hr><h2>GET</h2><br>";
    foreach($_GET  as  $varName  =>  $value)  
    {  
      $dv=$value;
          print  "Variable:  $varName  Value:  $dv<br>";  
      };

  }  
Paul  Chateau
17-May-2005  03:01  
I  had  the  same  problem  with  foreach()  and  a  recursiv  function.  If  you  don't  want  to  spend  about  1  or  2  hours  to  solve  this  problem,  just  use  for()  loops  instead  of  foreach().
Some  Example:

$arr[]  =  array(1,"item1");
$arr[]  =  array(2,"item2");
$arr[]  =  array(1,"item3");
//$arr[]  =  ...

//doesn't  work
function  foo($x)  {
      global  $arr;  //  some  Array
      foreach($arr  as  $value)  {  
          if($value[0]  ==  $x)  {
                  echo  $value[1]."\n";
                  foo($value[0]);
          }
      }
}

//just  use  this
function  foo($x)  {
      global  $arr;  //  some  Array
      for($i=0;  $i  <  count($arr);  $i++)  {
          if($arr[$i][0]  ==  $x)  {
                  echo  $arr[$i][1]."\n";
                  foo($arr[$i][0]);
          }
      }
}

Paul  
badbrush  at  pixtur  dot  de
16-May-2005  02:22  
another  WARNING  about  report  #26396  having  status  "wont  fix":

Beware  of  using  foreach  in  recursive  functions  like...

function  sort_folders(&$items,  $parent,$level)  {
      foreach($items  as  $item)  {
          if($item->parent  ==  $parent)  {

                  print  $item;
                  //  call  recursively...
                  sort_folders(&$items,  $item,  $level+1);
              }
      }
}
                  
I  struggled  a  few  hours  with  this  code,  because  I  thought  the  passing  the  array  by  reference  would  be  the  problem.  Infact  you  can  only  have  ONE  foreach  for  an  array  at  any  given  time.  A  foreach  inside  another  foreach  does  not  work.

The  manual  should  definately  give  some  hints  about  this  behaviour.

  pixtur  
Michael  T.  McGrew
13-May-2005  02:11  
This  can  be  used  to  creat  a  list  of  urls  for  a  nav  bar  or  links  section  etc.  If  you  draw  the  values  of  array  from  a  mysql  database  it  can  be  very  usefull.

<?php
$arr  =  array(news,  events);
foreach  ($arr  as  $value)  {
      echo  "<tr><td>Manage  <a  href=\"./".$value.".php\">".$value."</a></td></tr>";
}
?>
will  return
<tr>
<td>Manage  <a  href="./news.php">news</a>
</td>
</tr>
<tr><td>Manage  <a  href="./events.php">events</a>
</td>
</tr>  
Elvin
24-Apr-2005  05:10  
I  wrote  this  code  to  add  each  post  from  a  user  to  every  users'  txt  file.  But  it  only  adds  the  message  to  the  last  user  in  users.txt.  The  reason  of  that  is...(questmark)

<?php
session_start();
header("Cach-control:private");

$name=$_SESSION['name'];

$nameframe=$name.".txt";
$message=$_POST['message'];

$wierdchars  =  array("\'",  "\"",  "\\",  ":-)",  ":-D",  ":-p",  ":-(",  "=p",  ">:0",  ":-[",  ":-/",  ":-\\",  ":-X",  ":-?",  "B-)");

$newchars  =  array  (stripslashes("\'"),  stripslashes("\""),  "\\",  "<img  src='smile.gif'>",  "<img  src='opensmile.gif'>",  "<img  src='tounge.gif'>",  "<img  src='sad.gif'>",  "<img  src='tounge.gif'>",  "<img  src='yelling.gif'>",  "<img  src='embarrased.gif'>",  "<img  src='sosoleft.gif'>",  "<img  src='sosoright.gif'>",  "<img  src='quiet.gif'>",  "<img  src='confused.gif'>",  "<img  src='cool.gif'>");

$newmessage=str_replace($wierdchars,  $newchars,  $message);

$fontcolor=$_POST['fontcolor'];

$fontsize=$_POST['fontsize'];

$fontface=$_POST['fontface'];

$users=file("users.txt");

foreach($users  as  $user)
  {
$nameframed=$user.".txt";
$thefile=file_get_contents($nameframed);
$file=fopen($nameframed,  "w+");
$body=$name."|".$newmessage."\n";
$body2=$body.$thefile;
$write=fwrite($file,$body2);
fclose($file);
  }
echo  "<html><head><title>Adding  info...</title>";
echo  "<script>window.location='frame.php';</script>";
echo  "</head>";
echo  "<!--Removes  ads  form  page</head><body>";
?>  
ldv1970
27-Mar-2005  10:53  
To  the  18-Mar-2005  03:05  post:

See  URL:  http://bugs.php.net/bug.php?id=30914

The  behaviour  you  describe  is  incorrect,  but  the  problem  might  not  be  with  PHP  itself.  
19-Mar-2005  05:05  
It  seems  that  foreach  returns  different  variable  types  depending  on  which  syntax  you  use  and  which  version  of  PHP  you  are  running.  

If  you  use  this  syntax:

              foreach($array  as    $key  =>  $val)  {

then  the  $val  variable  is  a  string  (or  whatever  the  actual  value  in  the  array  is).

But  if  you  use  this  syntax:

              foreach($array  as    $val)  {

then  it  appears  that  the  $val  variable  is  an  array  in  PHP  4.3.10,  and  it  is  a  string  (or  whatever)  in  versions  4.3.1,  4.3.2,  and  4.3.6  (I  haven't  tested  any  other  version).  
xardas@spymac  com
20-Feb-2005  12:35  
Quote:
-------------------------
It  makes  sense,  since  you  cannot  call  only  keys  from  an  array  with  foreach().
-------------------------
Why  not?
<?php
foreach(array_keys($array)  as  $string)
{
print  'array  key  is  '.$string;
}
?>  
15-Dec-2004  12:29  
This  is  a  summary  of  bug  report  #26396  having  status  "wont  fix",  so  the  following  is  not  a  bug  (report),  but  may  need  extra  highlighting  so  the  novice  programmer  (like  me)  can  make  sense  of  the  second  note  given  above.

Note:    Also  note  that  foreach  operates  on  a  copy  of  the  specified  array  and  not  the  array  itself.  Therefore,  the  array  pointer  is  not  modified  as  with  the  each()  construct,  and  changes  to  the  array  element  returned  are  not  reflected  in  the  original  array.  However,  the  internal  pointer  of  the  original  array  is  advanced  with  the  processing  of  the  array.  Assuming  the  foreach  loop  runs  to  completion,  the  array's  internal  pointer  will  be  at  the  end  of  the  array.

<?
$myArray  =  array("a",  "b");

foreach($myArray  as  $anElement)  {
    foreach($myArray  as  $anotherElement)  {
      echo  $anotherElement;
    }
}
?>

results  in  "abab",  as  each  foreach  works  on  a  copy  of  $myArray.  

However:

<?
$myArray  =  array("a",  "b");

function  b()  {
    global  $myArray;
    
    foreach($myArray  as  $anotherElement)  {
      echo  $anotherElement;
    }
}

function  a()  {
    global  $myArray;
    
    foreach($myArray  as  $anElement)  {
      b();
    }
}

a();
?>

results  in  "ab",  ie.  both  foreach  work  on  the  same  instance  of  $myArray  because  it  is  referenced  as  a  global  variable.  Nevertheless,  to  the  casual  observer  both  variants  seem  equivalent  and  therefore  should  produce  the  same  output.  
gardan  at  gmx  dot  de
08-Oct-2004  04:21  
(PHP  5.0.2)
Pay  attention  if  using  the  same  variable  for  $value  in  both  referenced  and  unreferenced  loops.

$arr  =  array(1  =>  array(1,  2),  2  =>  array(1,  2),  3  =>  array(1,  2));
foreach($arr  as  &$value)  {  }
foreach(array(1,2,3,4,5)  as  $value)  {  }
echo  $test[3];

What  happens  here  is  that  after  the  first  foreach()  loop,  you  have  in  $value  a  reference  to  the  last  element  of  $arr  (here:  array(1,  2)).

Upon  entering  the  second  foreach(),  php  assigns  the  value.  Now  value  is  assigned  to  where  $value  (which  is  still  a  reference)  points,  that  is,  the  last  element  of  $arr.

Your  output  will  be  "5",  not  the  expected  "Array".  To  be  on  the  safe  side,  unset($value)  before  entering  the  next  foreach().  
Scarab  <scarab_at_scarab_dot_name>
29-Jun-2004  10:43  
It  is  possible  to  suppress  error  messages  from  foreach,  using  type  casting:
<?
foreach((array)$myarr  as  $myvar)  {
...
}
?>  
turadg  at  berkeley  dot  edu
22-May-2004  09:19  
The  documentation  above  says  "the  internal  pointer  of  the  original  array  is  advanced  with  the  processing  of  the  array".  

In  my  experience,  it's  more  complicated  than  that.    Maybe  it's  a  bug  in  4.3.2  that  I'm  using.  

If  the  array  variable  is  created  by  =&  assignment,  then  it  works  as  described.    You  can  use  current()  within  the  loop  to  see  the  next  element.  

If  the  array  variable  is  created  by  an  =  assignment,  the  foreach()  doesn't  advance  the  pointer.    Instead  you  must  use  next()  within  the  loop  to  peek  ahead.  

The  code  below  demonstrates.    On  my  system,  the  output  is  the  same  for  both  blocks,  though  one  uses  next()  and  the  other  current().  

<?php  
$originalArray  =  array("first",  "second",  "third",  "fourth",  "fifth");  

print  "the  array:\n";  
print_r($originalArray);  

print  "\noriginalArray  with  next():\n";  
foreach  ($originalArray  as  $step)  {  
      $afterThis  =  next($originalArray);  
      print  "$step,$afterThis\n";  
}  

$aliasArray  =&  $originalArray;  

print  "\naliasArray  with  current():\n";  
foreach  ($aliasArray  as  $step)  {  
      $afterThis  =  current($aliasArray);  
      print  "$step,$afterThis\n";  
}  
?>  
scott  at  slerman  dot  net
18-Apr-2004  12:27  
Apparently  the  behavior  of  foreach  with  classes  changed  in  PHP5.  Normally,  foreach  operates  on  a  copy  of  the  array.  If  you  have  something  like

<?php
foreach  ($array  as  $value){
      $value  =  "foo";
}
?>

the  original  array  will  not  be  modified.  However,  testing  this  code  on  PHP5RC1

<?php

class  foobar  {
      
      var  $a;
      var  $b;
      
      function  foobar(){
              $this->a  =  "foo";
              $this->b  =  "bar";
      }
}

$a  =  new  foobar;
$b  =  new  foobar;
$c  =  new  foobar;

$arr  =  array('a'  =>  $a,  'b'  =>  $b,  'c'  =>  $c);

foreach  ($arr  as  $e){
      $e->a  =  'bah';
      $e->b  =  'blah';
}

var_dump($arr);

?>

resulted  in  the  following  output:

array(3)  {
    ["a"]=>
    object(foobar)#1  (2)  {
      ["a"]=>
      string(3)  "bah"
      ["b"]=>
      string(4)  "blah"
    }
    ["b"]=>
    object(foobar)#2  (2)  {
      ["a"]=>
      string(3)  "bah"
      ["b"]=>
      string(4)  "blah"
    }
    ["c"]=>
    object(foobar)#3  (2)  {
      ["a"]=>
      string(3)  "bah"
      ["b"]=>
      string(4)  "blah"
    }
}

It  would  seem  that  classes  are  actually  passed  by  reference  in  foreach,  or  at  least  that  methods  are  called  on  the  original  objects.  
jazfresh  at  hotmail  dot  com
18-Feb-2004  03:50  
There  is  a  really  really  big  pitfall  to  watch  out  for  if  you  are  using  "foreach"  and  references.

Recall  this  example:
<?
$a  =  "Hello";
$b  =&  $a;    //  $b  now  refers  to  "Hello"
$b  =  "Goodbye";  //  BOTH  $a  and  $b  now  refer  to  "Goodbye"
?>

This  also  applies  to  the  loop  variable  in  a  foreach  construct.  This  can  be  a  problem  if  the  loop  variable  has  already  been  defined  as  a  reference  to  something  else.

For  example:
<?
//  Create  some  objects  and  store  them  in  an  array
$my_objects  =  array();
for($a  =  0;  $a  <  $num_objects;  $a++)  {
    $obj  =&  new  MyObject();
    $obj->doSomething();
    $my_objects[]  =&  $obj;
}

//  later  on  in  the  same  function...
foreach($my_objects  as  $obj)  {  //  Note  that  we  are  trying  to  re-use  $obj  as  the  loop  variable
    $obj->doSomethingElse();
}
?>

When  the  "for"  loop  exits,  $obj  is  a  reference  to  the  last  MyObject  that  was  created,  which  is  also  the  last  element  in  the  "my_objects"  array.

On  every  iteration,  the  foreach  loop  will  do  the  equivalent  of:

<?
$obj  =  $my_objects[$internal_counter++];
?>

$obj  will  now  refer  to  the  appropriate  element  in  the  array.

But  recall  the  reference  example  at  the  top.  Because  $obj  was  already  defined  as  a  reference,  any  assignment  to  $obj  will  overwrite  what  $obj  was  referring  to.  So  in  other  words,  on  every  foreach  loop  iteration,  the  last  element  in  the  array  will  be  overwritten  with  the  current  array  element.

To  avoid  this  problem,  either  use  a  differently  named  loop  variable,  or  call  "unset()"  on  the  loop  variable  before  you  begin  the  foreach().

It  would  be  more  intuitive  PHP  unset()  the  loop  variable  before  a  foreach  began,  maybe  they'll  put  that  in  a  later  version.  
andy  at  barbigerous  dot  net
07-Feb-2004  03:05  
For  dual  iteration,  the  internal  pointers  may  need  resetting  if  they've  been  previously  used  in  a  foreach.

<?PHP

for(
          $someArray1.reset(),  
          $someArray2.reset();
          list(,  $someValue1  )  =  each(  $someArray1  )  ,
          list(,  $someValue2  )  =  each(  $someArray2  )
          ;
)  {

  echo  $someValue1;
  echo  $someValue2;

}

?>  
thomas  dot  kaarud  at  netcom  dot  no
03-Feb-2004  10:41  
A  more  elegant  way  to  do  this,  without  involving  new  arrays  or  making  PHP5-specific  code,  would  be:

<?php
foreach  ($a  as  $x  =>  $a)  {
      echo  "$b[$x]  :  $a";  }
?>  
Joseph  Kuan
15-Jan-2004  02:42  
<?php  
Or  use  array_combine.  

$c  =  array_combine($a,  $b)  
foreach($c  as  $aKey  =>  $bVal)  {  
      echo  $aKey;  
      echo  $bVal;  
}  
?>  
endofyourself  at  yahoo  dot  com
02-Jan-2004  08:36  
If  you  are  trying  to  do  something  like:

<?PHP

foreach(
          $someArray1  as  $someValue1  ,
          $someArray2  as  $someValue2
)  {

  echo  $someValue1;
  echo  $someValue2;

}

?>

Pleas  note  that  this  IS  NOT  possible  (although  it  would  be  cool).  However,  here  is  another  way  to  acheive  a  similar  effect:

<?PHP

for(
          ;
          list(,  $someValue1  )  =  each(  $someArray1  )  ,
          list(,  $someValue2  )  =  each(  $someArray2  )
          ;
)  {

  echo  $someValue1;
  echo  $someValue2;

}

?>  
php  at  electricsurfer  dot  com
23-Apr-2003  05:33  
[Ed  Note:    You  can  also  use  array_keys()  so  that  you  don't  have  to  have  the  $value_copy  variable  --alindeman  at  php.net]  

I  use  the  following  to  modify  the  original  values  of  the  array:  

<?php  
foreach  ($array  as  $key=>$value_copy)  
{  
          $value  =&  $array[$key];  
          //  ...  
          $value  =  'New  Value';  
}  
?>  
ian  at  NO_SPAM  dot  verteron  dot  net
02-Jan-2003  08:29  
Note  that  foreach  is  faster  than  while!  If  you  can  replace  the  following:  

<?php  
reset($array);  
while(list($key,  $val)  =  each($array))  
{  
    $array[$key]  =  $val  +  1;  
}  
?>  

...with  this  (although  there  are  functional  differences,  but  for  many  purposes  this  replacement  will  behave  the  same  way)...  

<?php  
foreach($array  as  $key  =>  $val)  
{  
    $array[$key]  =  $val  +  1;  
}  
?>  

You  will  notice  about  30%  -  40%  speed  increase  over  many  iterations.  Might  be  important  for  those  ultra-tight  loops  :)  
18-Sep-2002  01:06  
"Also  note  that  foreach  operates  on  a  copy  of  the  specified  array,  not  the  array  itself,  therefore  the  array  pointer  is  not  modified  as  with  the  each()  construct  and  changes  to  the  array  element  returned  are  not  reflected  in  the  original  array."

In  other  words,  this  will  work  (not  too  expected):
foreach  ($array  as  $array)  {
      //  ...
}

While  this  won't:
while  (list(,  $array)  =  each($array))  {
      //  ...
}

2654 view

4.0 stars