Reputation: 556
Is possible in php to reset The foreach?
for example:
foreach($rows as $row)
{
if(something true)
{
continue foreach;
}
else
{
break;
reset foreach;//I mean start foreach again...
}
}
----------------------------------Edited
Thanks my friend for your answers...
The condition generate from result of foreach so I can not use function. I wana sortet it by (fro example) alphabet...in many DIV html. I can not filter result by SQL for same reson.
So mybe I have to use a css trick.
Upvotes: 7
Views: 16185
Reputation: 69
You can reset the foreach with: "using it in this below as well"
$value = "";
Or restart by pointing where to go after the end:
a:
"as restarting"
goto a;
So in the code from the asker in this post do like this:
a:
foreach($rows as $row){
$value++;
if(something true){
continue foreach;
}
else {
break;
$value = ""; // A value reset
goto a; //I mean start foreach again...
}
$value = ""; //perhaps a value reset here?
}
Upvotes: 0
Reputation: 4738
Try using reset/while/each which is functionally equivalent to foreach according to the manual then you can use reset within the loop like so:
<?php
$arr = array(1=>'one',2=>'two',3=>'three');
reset($arr);
$resets=0;
while (list($key, $value) = each($arr))
{
echo "$key => $value<br />\n";
if($value=='three')
{
if($resets==0){$resets++;echo "==Resetting==<br />\n";reset($arr);continue;}
}
}
Output:
1 => one 2 => two 3 => three ==Resetting== 1 => one 2 => two 3 => three
As pointed out by Mike Kormendy in the comments, each is deprecated as of php 7.2.
If for some reason you like my approach, you can emulate each using a combination of key(), current(), and next() like so:
<?php
$arr = array(1=>'one',2=>'two',3=>'three');
reset($arr);
$resets=0;
while ( list($key,$value) = [key($arr),current($arr)] )
{
if($key === NULL){ break; }
next($arr);
echo "$key => $value<br />\n";
if($value=='three')
{
if($resets==0){$resets++;echo "==Resetting==<br />\n";reset($arr);continue;}
}
}
Output:
1 => one 2 => two 3 => three ==Resetting== 1 => one 2 => two 3 => three
This answer was posted many years ago.
Going forward, I'd avoid this type of approach like the plague.
The accepted answer is a lot more elegant.
Upvotes: 2
Reputation: 4666
Yes it is possible to reset a foreach but not the way you described it in your question. You can read my approaches below.
--------- Implement Iterator --------------------------------
Implement the Iterator interface.
Link: https://www.php.net/manual/en/class.iterator.php.
Code example:
class myIterator implements Iterator {
private $maxIterations = 2; // the maxumum amount of iterations
private $currentIteration = 1; // the current iteration number
private $lastKey = null;
private $lastValue = null;
private $currentValue = null;
private $position = 0;
private $array;
public function __construct($array) {
$this->array = $array;
end($array);
$this->lastKey = key($array);
$this->lastValue = current($array);
}
public function rewind() {
$this->position = 0;
reset($this->array);
}
public function valid() {
// Reset when there are no elements
if($this->position > $this->lastKey &&
$this->currentValue === $this->lastValue &&
$this->currentIteration < $this->maxIterations){
$this->rewind();
++$this->currentIteration;
}
$isSet = isset($this->array[$this->position]);
return $isSet;
}
public function current() {
$this->currentValue = $this->array[$this->position];
return $this->currentValue;
}
public function key() {
return $this->position;
}
public function next() {
++$this->position;
}
}
$array = array("A",
"B",
"C",
);
$it = new myIterator($array);
// the iterator will traverse the array twice
foreach($it as $key => $value) {
echo 'key : ' . $key . '<br>';
echo 'val : ' . $value . '<br>';
echo '<br>';
}
The output
key : 0
val : A
key : 1
val : B
key : 2
val : C
key : 0
val : A
key : 1
val : B
key : 2
val : C
--------- InfiniteIterator + LimitIterator --------------------------------
You can use InfiniteIterator in combination with LimitIterator.
$obj = new stdClass();
$obj->Mon = "Monday";
$obj->Tue = "Tuesday";
$obj->Wed = "Wednesday";
$obj->Thu = "Thursday";
$obj->Fri = "Friday";
$obj->Sat = "Saturday";
$obj->Sun = "Sunday";
$infinate = new InfiniteIterator(new ArrayIterator($obj));
foreach ( new LimitIterator($infinate, 0, 14) as $value ) {
print($value . PHP_EOL);
}
// OUTPUT:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
See link: http://php.net/manual/en/class.infiniteiterator.php
--------- ArrayObject + ArrayIterator --------------------------------
According to the PHP manual it should also be possible to achieve it by using ArrayIterator.
When you want to iterate over the same array multiple times you need to instantiate ArrayObject and let it create ArrayIterator instances that refer to it either by using foreach or by calling its getIterator() method manually.
Their description is not clear to me, but it think that they mean something like this.
$array = array('honda', 'toyota', 'suzuki', 'mazda', 'nissan');
end($array);
$lastKey = key($array);
$maxIterations = 2;
$currentIteration = 1;
$arrayObj = new ArrayObject($array);
for($iterator = $arrayObj->getIterator(); $iterator->valid(); $iterator->next()){
echo $iterator->key() . ' : ' . $iterator->current() . '<br>';
if( $iterator->key() === $lastKey &&
$currentIteration < $maxIterations ){
$iterator->rewind();
++$currentIteration;
echo $iterator->key() . ' : ' . $iterator->current() . '<br>';
}
}
OUTPUT:
0 : honda
1 : toyota
2 : suzuki
3 : mazda
4 : nissan
0 : honda
1 : toyota
2 : suzuki
3 : mazda
4 : nissan
Link: http://php.net/manual/en/class.arrayiterator.php
Upvotes: 0
Reputation: 5931
You could do something around these lines (and avoid the limitations of recursion):
while (True) {
$reset = False;
foreach ($rows as $row) {
if(something true) {
continue;
} else {
$reset = True;
break;
}
}
if ( ! $reset ) {
break; # break out of the while(true)
}
# otherwise the foreach loop is `reset`
}
Upvotes: 9
Reputation: 446
Why reset the foreach ? If you really need this... But care about infinite loop !
function myForeach($array){
foreachforeach($rows as $row){
if(something true){
continue foreach;
}else{
myForeach($array);
}
Upvotes: 1
Reputation: 505
I think you can do that by putting the for each in a function and then calling the function from itself.
function doForEach($rows) {
foreach($rows as $row)
{
if(something true)
{
continue foreach;
}
else
{
break;
doForEach($rows);
}
}
}
Be very careful with this however, you'll likely end up in a loop.
Upvotes: 1
Reputation: 57709
It seems that reset
inside a foreach
has no effect.
You can implement this if you make your own Traversable
.
Upvotes: 3