I tested different loops. Here is my test script :

┌─(yoda@ev5)(14:32:05)
└─(~/var/www/test)-> cat for_foreach_while.php 
#!/usr/bin/php
<?php
 
define('N', "\n");
 
error_reporting(E_ALL | E_NOTICE);
 
$nbLoop = 10000;
 
$testArray = array_fill(0, 500, 'toto');
 
$time = array();
 
$desc = array(
	'iterating an array with a count + for',
	'iterating an array with a foreach',
	'iterating an array with a while',
);
 
 
/**
 * iterating with for
 */
echo 'Starting test 1'.N;
$time[0]['start'] = microtime(true);
 
for($i = 0; $i < $nbLoop; $i++) {
	$nb = count($testArray);
	for($j = ($nb - 1); $j > 0; $j--) {
	}
}
 
$time[0]['stop'] = microtime(true);
echo 'Test 1 ended'.N;
 
/**
 * iterating with foreach
 */
echo 'Starting test 2'.N;
$time[1]['start'] = microtime(true);
 
for($i = 0; $i < $nbLoop; $i++) {
	foreach($testArray as $k => $v) {
	}
}
 
$time[1]['stop'] = microtime(true);
echo 'Test 2 stopped'.N;
 
 
/**
 * iterating with while(list() = each())
 */
echo 'Starting test 3'.N;
$time[2]['start'] = microtime(true);
 
for($i = 0; $i < $nbLoop; $i++) {
	while(list($k, $v) = each($testArray)) {
	}
	reset($testArray);
}
 
$time[2]['stop'] = microtime(true);
echo 'Test 3 ended'.N;
 
 
$differences = array();
echo 'results: '.N;
foreach($time as $k => $t) {
    echo 'echo test '.$k.' "'.sprintf('%40s', $desc[$k]).'" : '.($difference[$k] = $t['stop'] - $t['start']).N;
}

And the results are :

┌─(yoda@ev5)(14:32:47)
└─(~/var/www/test)-> php for_foreach_while.php 
Starting test 1
Test 1 ended
Starting test 2
Test 2 stopped
Starting test 3
Test 3 ended
results: 
echo test 0 "   iterating an array with a count + for" : 0.489103078842
echo test 1 "       iterating an array with a foreach" : 0.750061988831
echo test 2 "         iterating an array with a while" : 4.91836500168

The winner is count+for, followed by foreach, and while is far behind. I suppose it's because of the reset.

PHP: 5.2.12 (debian) in CLI

Special thanks to Folliked for remembering me that while still exists ;)