PHP 7.1.0 Released

goto

(PHP 5 >= 5.3.0, PHP 7)

¿Qué es lo peor que podría suceder si utiliza goto?
Imagen cortesía de » xkcd

El operador goto puede ser usado para saltar a otra sección en el programa. El punto de destino es especificado mediante una etiqueta seguida de dos puntos y la instrucción es dada como goto seguida de la etiqueta del destino deseado. Este goto no es completamente sin restricciones. La etiqueta de destino debe estar dentro del mismo fichero y contexto, lo que significa que no se puede saltar fuera de una función o método, ni se puede saltar dentro de uno. Tampoco se puede saltar dentro de cualquier clase de estructura de bucle o switch. Se puede saltar fuera de estos y un uso común es utilizar un goto en lugar de un break multi-nivel.

Ejemplo #1 Ejemplo de goto

<?php
goto a;
echo 
'Foo';
 
a:
echo 
'Bar';
?>

El resultado del ejemplo sería:

Bar

Ejemplo #2 Ejemplo de goto en un bucle

<?php
for($i=0,$j=50$i<100$i++) {
  while(
$j--) {
    if(
$j==17) goto end;
  }  
}
echo 
"i = $i";
end:
echo 
'j alcanzó 17';
?>

El resultado del ejemplo sería:

j alcanzó 17

Ejemplo #3 Esto no funcionará

<?php
goto loop;
for(
$i=0,$j=50$i<100$i++) {
  while(
$j--) {
    
loop:
  }
}
echo 
"$i = $i";
?>

El resultado del ejemplo sería:

Fatal error: 'goto' into loop or switch statement is disallowed in script on line 2
(Error fatal: 'goto' hacia el interior de un bucle o sentencia switch no esta permitido en el script en la línea 2)

Nota:

El operador goto está disponible a partir de PHP 5.3.

add a note add a note

User Contributed Notes 8 notes

up
50
chrisstocktonaz at gmail dot com
7 years ago
Remember if you are not a fan of wild labels hanging around you are free to use braces in this construct creating a slightly cleaner look. Labels also are always executed and do not need to be called to have their associated code block ran. A purposeless example is below.

<?php

$headers
= Array('subject', 'bcc', 'to', 'cc', 'date', 'sender');
$position = 0;

hIterator: {

   
$c = 0;
    echo
$headers[$position] . PHP_EOL;

   
cIterator: {
        echo
' ' . $headers[$position][$c] . PHP_EOL;

        if(!isset(
$headers[$position][++$c])) {
            goto
cIteratorExit;
        }
        goto
cIterator;
    }

   
cIteratorExit: {
        if(isset(
$headers[++$position])) {
            goto
hIterator;
        }
    }
}
?>
up
37
Ray dot Paseur at Gmail dot com
5 years ago
You cannot implement a Fortran-style "computed GOTO" in PHP because the label cannot be a variable. See: http://en.wikipedia.org/wiki/Considered_harmful

<?php // RAY_goto.php
error_reporting(E_ALL);

// DEMONSTRATE THAT THE GOTO LABEL IS CASE-SENSITIVE

goto a;
echo
'Foo';
a: echo 'Bar';

goto
A;
echo
'Foo';
A: echo 'Baz';

// CAN THE GOTO LABEL BE A VARIABLE?

$a = 'abc';
goto
$a; // NOPE: PARSE ERROR
echo 'Foo';
abc: echo 'Boom';
?>
up
10
D. Kellner
1 year ago
However hated, goto is useful. When we say "useful" we don't mean "it should be used all the time" but that there are certain situations when it comes in handy.

There are times when you need a logical structure like this:
<?php
// ...
do {

   
$answer = checkFirstSource();
    if(
seemsGood($answer)) break;

   
$answer = readFromAnotherSource();
    if(
seemsGood($answer)) break;

   
// ...

}while(0);
$answer = applyFinalTouches($answer);
return
$answer;
?>

In this case, you certainly implemented a goto with a "fake loop pattern".  It could be a lot more readable with a goto; unless, of course, you hate it.  But the logic is clear: try everything you can to get $answer, and whenever it seems good (e.g. not empty), jump happily to the point where you format it and give it back to the caller.  It's a proper implementation of a simple fallback mechanism.

Basically, the fight against goto is just a side effect of a misleading article many decades ago.  Those monsters are gone now.  Feel free to use it when you know what you're doing.
up
14
sixoclockish at gmail dot com
4 years ago
You are also allowed to jump backwards with a goto statement. To run a block of goto as one block is as follows:
example has a prefix of iw_ to keep label groups structured and an extra underscore to do a backwards goto.

Note the `iw_end_gt` to get out of the labels area

<?php
    $link
= true;

    if (
$link ) goto iw_link_begin;
    if(
false) iw__link_begin:
   
    if (
$link ) goto iw_link_text;
    if(
false) iw__link_text:
   
    if (
$link ) goto iw_link_end;
    if(
false) iw__link_end:
   
    goto
iw_end_gt;
   
   
    if (
false) iw_link_begin:
        echo
'<a href="#">';
    goto
iw__link_begin;
   
    if (
false) iw_link_text:
        echo
'Sample Text';
    goto
iw__link_text;
   
    if (
false) iw_link_end:
        echo
'</a>';
    goto
iw__link_end;
   
   
iw_end_gt:
?>
up
6
f at francislacroix dot info
5 years ago
The goto operator CAN be evaluated with eval, provided the label is in the eval'd code:

<?php
a
: eval("goto a;"); // undefined label 'a'
eval("a: goto a;"); // works
?>

It's because PHP does not consider the eval'd code, containing the label, to be in the same "file" as the goto statement.
up
-3
kle at lekhoi dot com
5 months ago
Goto can also go into an infinite loop as the example below.

<?php

goto start;

start: echo 'start';

working: {
    echo
'working';
    ...
    goto
start;
    echo
'never executed';
}
?>

Output
startworkingstartworking ...
up
-7
ivan dot tc at gmail dot com
1 year ago
This works good:

<?php
goto start;

five:
echo
$i;
goto
end;

start:
echo
'I have ';

for (
$i=0; $i < 10; $i++) {
  if (
$i == 5) {
    goto
five;
  }
}

end:
echo
' apples';
?>

Output: I have 5 apples.

This don't work:

<?php
goto start;

five:
echo
$i;
goto
end;

start:
echo
'I have ';
$count();

end:
echo
' apples';

$count = function () {
  for (
$i=0; $i < 10; $i++) {
    if (
$i == 5) {
      goto
five; // line 18
   
}
  }
}
?>

PHP Fatal error:  'goto' to undefined label 'five' on line 18
up
-21
ivan dot sammartino at gmail dot com
1 year ago
I found it useful for switch statements:

<?php
$action
= $_GET['action'];
switch (
$action){
    case(
'a'):
       
mylabel: {
           
doStuff();
            break;
        }
    case(
'b'):
        if (
true){
           
doAnotherStuff();
        } else {
            goto
mylabel;
        }
        break;
}
?>
To Top