GOTO itself is not an immediate problem, it's the implicit state machines that people tend to implement with it. In your case, you want code that checks whether the IP address is in the list of allowed addresses, hence
if (!contains($ips, $ip)) throw new Exception('Not allowed');
so your code wants to check a condition. The algorithm to implement this check should be of no concern here, in the mental space of your main program the check is atomic. That's how it should be.
But if you put the code that does the check into your main program, you lose that. You introduce mutable state, either explicitly:
$list_contains_ip = undef; # STATE: we don't know yet
foreach ($ips as $i) {
if ($ip === $i) {
$list_contains_ip = true; # STATE: positive
break;
}
# STATE: we still don't know yet, huh?
}
# Well, then...
$list_contains_ip = false; # STATE: negative
if (!$list_contains_ip) {
throw new Exception('Not allowed');
}
where $list_contains_ip is your only state variable, or implicitly:
# STATE: unknown
foreach ($ips as $i) { # What are we checking here anyway?
if ($ip === $i) {
goto allowed; # STATE: positive
}
# STATE: unknown
}
# guess this means STATE: negative
throw new Exception('Not allowed');
allowed: # Guess we jumped over the trap door
As you see, there's an undeclared state variable in the GOTO construct. That's not a problem per se, but these state variables are like pebbles: carrying one is not hard, carrying a bag full of them will make you sweat. Your code will not stay the same: next month you'll be asked to differentiate between private and public addresses. The month after that, your code will need to support IP ranges. Next year, someone will ask you to support IPv6 addresses. In no time, your code will look like this:
if ($ip =~ /:/) goto IP_V6;
if ($ip =~ /\//) goto IP_RANGE;
if ($ip =~ /^10\./) goto IP_IS_PRIVATE;
foreach ($ips as $i) { ... }
IP_IS_PRIVATE:
foreach ($ip_priv as $i) { ... }
IP_V6:
foreach ($ipv6 as $i) { ... }
IP_RANGE:
# i don't even want to know how you'd implement that
ALLOWED:
# Wait, is this code even correct?
# There seems to be a bug in here.
And whoever has to debug that code will curse you and your children.
Dijkstra puts it like this:
The unbridled use of the go to statement has as an immediate consequence that it becomes terribly hard to find a meaningful set of coordinates in which to describe the process progress.
And that's why GOTO is considered harmful.
in_arrayfunction, using which you can eliminate the loop, so it becomesif(!in_array($ip, $ips, TRUE)) new Exception('Not allowed');– CodesInChaos 19 hours ago