Search code examples
phpsubstitutiongoto

Emulate goto functionality in PHP 5.2 - maybe better approach?


I have written a script using my local PHP 5.3 installation making use of the goto statement. Uploading it to my webserver, I had to discover that my hoster still has PHP 5.2 installed and therefore doesn't support goto. My question is therefore how to emulate goto's functionality in the following context:

foo();

iterator_start:

foreach ($array as $array_item) {
    switch ($array_item) {
        case A:
            foo();
            break;
        case B:
            // Substitute
            array_splice($array, offset($array_item), 1, array(A, A, B, C));
            // Restart iterator
            goto iterator_start;
            break;
    }
}

The idea is that an array must be modified according to a set of substitution rules. Once a rule has been executed (which may modify any number of array items in any position, replace them, even delete them) everything must start from zero because the entire array may have changed in an unpredictable fashion (thus recursive substitution rules are allowed as well). The solution I use, with goto simply jumping to the start of the loop after each substitution, seems very straightforward and even quite clean to me, but as I mentioned I cannot use it on my webserver.

Is there any substitute for goto here, or can the same task be accomplished in an entirely different manner (preferably without changing too much code)?

Any ideas are appreciated.


A polite request: Please spare me any lectures on the usefulness or dangers of goto here. I've read PHP and the goto statement to be added in PHP 5.3 and know about spaghetti code and all those en vogue "considered harmful" letters from the 1980s. Discussing the supposed evil of goto has nothing to do with my question, and treating any program construct as "bad style" per se is simply dogma, which has no place in my programming ideology.


Solution

  • You can use each() in a while loop. It uses the internal array cursor to retrieve the current element in the array and move the cursor to the next one. When slicing the array, reset to cursor to restart from the start of the array at the next while loop iteration. Calling reset() is probably not even required, it's probably a side effect of array_splice() since it changes the array.

    foo();
    while (list($key, $array_item) = each($array)) {
      switch ($array_item) {
        case A:
          foo();
          break;
        case B:
          // Substitute
          array_splice($array, offset($array_item), 1, array(A, A, B, C));
          // Reset array cursor, this is probably not necessary 
          reset($array);
          break;
      }
    }