It's easy to abuse the switch syntax to do some very useful things. As this example will show, the possibilities can go beyond even Duff's Device-style craziness (not that this example is nearly as clever as Duff's Device, but it demonstrates how you can do certain things other than simply the increment/decrement/assignment that's possible in C).
Fundamentally, this works mostly due to the fact that, from the point of view of the assembler/interpreter, a switch block is hardly any different from a bunch of GOTO labels and if() evaluations. But, like an if() evaluation, the line of a case: statement is evaluated as an expression. So, in this case, we can perform an assignment and match the result of that assignment, because the return value of an assignment is the data that was assigned (and not the value of the variable it was assigned to, as you might expect).
So far, this is not actually amazing, even if it is a bit unintuitive. From a language point-of-view, it would be the same as an if($var = "string") statement which is using an assignment (=) rather than a comparison (==) operator. When you look at the pre-processing optimization, because a normal assignment of $var = "string" will always equal "string", it makes sense to have the result of that expression simply be equal to the right side of the expression (the right side is used rather than the left to let the assembler/interpreter work faster, on account of how they traditionally simply change the memory location for the assigned variable rather than copy the memory around unnecessarily).
Where this becomes more interesting is where, in PHP, you have language constructs that behave like functions but are used like statements. An $array[] = "string" expression is actually a language construct that just happens to behave a lot like a function, but you use it in the same way that you use an assignment expression, and like an expression, it always evaluates to the right side of the expression; in this case, "string" and not array() .
The assembler/interpreter can't use the right side of the expression as a shortcut for the result of a function, so you can't use functions in this way in a case statement. You also can't get around this limit on calling functions from the case line by using variable functions, because they are used in the same way as functions.
But imagine what you could do with other language constructs, like eval() or include() !
Consider the following:
<?php
function flavor($type = null)
{
switch ($type) {
default:
$type = null;
case $array[] = "chocolate":
if ($type != null) {
$array = array($type);
break;
}
case $array[] = "strawberry":
if ($type != null) {
$array = array($type);
break;
}
case $array[] = "vanilla":
if ($type != null) {
$array = array($type);
break;
}
}
if ( (count($array) != 1) ) {
return "Flavors available: " . implode(", ", $array);
} else {
return "Flavor selected: " . implode(", ", $array);
}
}
echo flavor() . "<br>";
echo flavor("banana") . "<br>";
echo flavor("chocolate") . "<br>";
?>
What makes this example useful is that you don't need a variable somewhere that contains the available options (even within the function itself), so to support new options, you only ever have to change the code to add the new option - you don't need to update some variable somewhere that controls whether or not it works or whether or not people can tell that there's a new option.