Now that you are aware that "else is hard" we can look at the default statement which essentially gives the switch an "else" or catch all option. If you end a switch with a default statement then if none of the case statements are obeyed the default is. For example:
switch ($a){ case 1: instructions1; break; case 2: instructions2; break; case 3: instructions3; break; case 4: instructions4; break; default: default instructions; break; }
You can see that the default instructions are only obeyed if none of the other conditions hold - that is if $a isn't equal to 1, 2, 3 or 4. As with all "else" type of constructions you should ask yourself what the condition is that causes the default statement to be obeyed? The answer is that the condition that is true when the default instructions are obeyed is $a<1 or $a>4.
elseif
It can be difficult to work out when an else or a default is going to be obeyed but there is a conditional instruction that is even tougher to get right - the elseif. The elseif can be placed within an if statement in the same way as an else but it can include a condition that has to be true before its instructions are obeyed. You can have as many additional elseifs within a single if and have a final else to deal with anything that doesn't satisfy any of the conditions.
The idea is that you can use the elseif to place additional conditions on the else part of the if statement. For example:
$a=3; if($a==1){ echo("the value is one"); }elseif($a==2){ echo("the value is two"); }elseif($a==3){ echo("the value is three"); }else{ echo("the value is none of the above"); }
In this case the first echo is obeyed if $a is one. If this isn't the case then the elseif is evaluated and its echo statement is only obeyed if $a isn't one but is equal to two. Similarly the third echo statement is only obeyed if a$ isn't one or two but is equal to three. The final echo is only obeyed if a$ isn't one, two or three.
You can see that the elseif gives us an alternative way to implement a switch but usually when an if statement is easily reducible to a switch then it is better to use a switch. The real power and so danger of the elseif occurs when the conditions are such that they aren't mutually exclusive - in the previous example $a could only be one of the values specified. Consider the following small modification on the previous example:
$a=1; $b=2; $c=3; if($a==1){ echo("the value of a is one"); }elseif($b==2){ echo("the value of b is two"); }elseif($c==3){ echo("the value of c is three"); }else{ echo("what is the condition?"); }
What is printed? The answer is that the first echo is obeyed because $a is one and the else parts of the if statement aren't even considered because the if condition is true. However, if $a was a value other than one then what would be printed would depend on the value of $b or $c. Notice that only one of the messages would ever appear because as soon as a condition evaluates to true the following elseifs or else are skipped.
Now answer the final question - what is the condition that is satisfied for the echo belonging to the else to be obeyed?
The answer is that $a has to be something other than one, $b has to be something other than 2 and $c has to be something other than 3 i.e. ($a!=1) and ($b!=2) and ($c!=3) has to be true.
In general when you are reading or trying to understand a complicated if-elseif-else construction always remember that for the if part to be obeyed the first condition has to be true. For the first elseif to be obeyed the first condition has to be false and the second condition true. For the second else if the first two conditions have to be false and the third has to be true and so on down to the final else for which all of the conditions have to be false.
If the else is hard the elseif can be very hard. Building complicated if statements is error prone but sometimes there is no choice. Always try to create the if statement or the switch that best conveys your meaning and always check that the elseif, else or default conditions are what you expect.
In most cases the if or the if else is enough to build a program. A basic if-else statement selects between two alternatives and you can put these together to select between as many alternatives as you like. In this sense you really don't need anything more but to make programming easier PHP provides a number of additional instructions that make multiway selections easier - the switch and the elseif. Both are easy enough to understand but they both are sufficiently flexible and powerful to be easily misused.
More than two ways – the switch
The previous example shows that sometimes you have to use if statements in combination to make things work correctly. A simple if can be though of as a one way selection – do this if the condition is true.
if($a==1){
echo "do this only if the condition is true";
}
An if-else can be though of as a two way selection – do this if the condition is true and do that if the condition is false.
if($a==1){
echo "do this only if the condition is true";
}else{
echo "do this only if the condition is false";
}
You can see that by using multiple if statements you can construct any selection of actions based on a set of conditions you care to think up.
For example you can use a set of sequential ifs to select one out of a number of possible things to do:
if($a==1){
echo "the value is 1";
}
if($a==2){
echo "the value is 2";
}
if($a==3){
echo "the value is 3";;
}
if($a==4){
echo "the value is 4";;
}
You can see that only one of the conditions can be true (assuming that $a isn’t changed by any of the instructions that are part of the if) and so only one of the set of instructions will be obeyed.
If you trace the flow of control you will discover that there are four separate paths though the instructions depending on the value stored in $a. A cleaned up version of the shape of this flow of control can be seen below:
***nway.jpg
This sort of multiple selection based on the value of a single variable or expression is so common that PHP and most other languages provide a special instruction that makes it easier to write and easier to understand. The switch statement really can be thought of as a switch determining which instruction is executed.
The switch always takes the same form:
switch(expression)
{
list of cases
}
The list of cases is made up of a set of specifications and instructions:
case value:
instructions;
break;
The instructions following the case are only carried out if the switch expression is equal to the value. The break marks the end of the case.
For example, our previous list of if statements are equivalent to the following switch:
switch ($a){
case 1:
instructions1;
break;
case 2:
instructions2;
break;
case 3:
instructions3;
break;
case 4:
instructions4;
break;
}
The switch statement is obeyed by first evaluating the switch expression, $a in this case. The value is then compared to each of the case values in turn. If it matches a case value then the instructions following the case are obeyed and when the break is executed control passes to the instruction following the switch’s closing curly bracket. That is the break really can be though of as breaking out of the entire switch statement and moving on to what follows.
That is one and only one case and its list of instructions will be carried out according to the value of the switch expression. For this reason you should switch when only one of a number of possibilities apply.
Notice also that the switch expression can be complicated but everything works as an expression always evaluates to a single value which is then used to select which of the case blocks is obeyed. For example, the expression and the values can be a string:
switch($gender){
case "male"
echo "hello sir how can I help?";
break;
case "female"
echo "hello madam how can I help?";
break;
}
notice that this is just a two way selection and so could just as easily be written as two if statements or an if-else. Which form of expression you choose is a matter of taste but you need to be aware that the if-else form is slightly tricker than it first seems.
No break!
Now we come to a complication that you should skip if this is the first time you have encountered the switch statement or anything like it.
If you simply use the switch as described then its easy to use and understand and most programmers advice is to stick to this. However the break that ends each case is optional. If you leave out then the flow of control passes to the next case below and so on until either it reaches a break or the end of the switch statement. For example:
switch ($a){
case 1:
instructions1;
case 2:
instructions2;
break;
}
If $a is 1 then instructions1 are carried out but without a break at the end of case 1 control falls through to the second case and instructions2 are also carried out. If $a is 2 then only case 2 is obeyed.
You should, of course, never leave out the break by accident. The result is code that doesn't do what you expect and this can be very difficult to find as programmers some times tend to read a "break" were no break exists simply from habit.
It is also sometimes tempting to leave out a break statement because it seems to fit in with what you want the code to do. For example:
switch($gender)
case "female"
echo "Don't forget to visit our sister site!";
case "male"
echo "Welcome to a new member.";
break;
}
This adds a special message for new female members of the site but by not including a break makes sure that they also get the same message that a male gets. This saves having to add the default message to the female case but it also makes the code more fragile. Notice that the order of the case statements now matter if you swap the order of the male and female case statements the code no longer works. The same thing happens if you come back at a later date and add another case statement between the male and female case statements - admittedly not likely in this example but in general it often happens.
The key idea is that when you make use of fortuitous relationships between cases by leaving out the break you create a switch that is more fragile in the sense that it is sensitive to small changes in the code that switch statements using break tolerate. That is the order of the case statements now matter. Fragile code is something best avoided if there is an alternative so it is recommended that you always use break.
else is hard
When you write an if statement then it is usually very easy to work out when the conditional instructions are obeyed. For example:
if($a>0){
echo("$a is positive);
}
then it is easy to say when the echo statement will be obeyed - when the condition is true and this translates to when the value stored in $a is greater than zero. Now consider the slightly modified example with an else clause
if($a>0){
echo("$a is positive);
}else{
echo("$a isn't positive);
}
Now you can see quite clearly that the echo that is in the else part of the statement is only obeyed when the condition is false or when the "not" of the condition is true - and programmers are usually not very good at working out when a condition is false or what the "not" of a condition is true. For example, in this case the else is obeyed when $a>0 is not true. That is when $a is 0 or less than zero. That is the "not" or logical converse of $a>1 is $a<=1. Most programmers would find this fairly obvious but it isn't trivial and it gets much more complicated very quickly.
Even in very simple situations the psychology of a condition can cause a programmer to make an error. For example,
if($gender=="male"){
echo("welcome sir");
}else{
echo("welcome madam");
}
The negation of the condition $gender=="male" is $gender!="male" which translates to if $genders is any other value than "male" then the else part of the statement is obeyed. Many novice programmers will assume that the negation of $gender=="male" is $gender=="female" because that's the way we think about it in the real world.
If you think that the above examples are trivial and you would never make a mistake with an else then perhaps a more advanced example will illustrate that "else really is hard". You can combine conditions using the "and" and "or" operators in a way that fits in with their normal meaning. For example, consider the following if statement:
$a=15;
if(($a>10) and ($a<20)){
echo("the value is between 10 and 20");
}else{
echo("the value isn't between 10 and 20");
}
Clearly first echo is obeyed if $a is greater than 10 and less than 20 i.e. both conditions have to be true. The else is obeyed when the whole condition works out to be false i.e. when $a isn't between 10 and 20.
Now can you write down the condition that is true when the else is obeyed?
It’s the negation of (($a>10) and ($a<20))
which works out to be ($a<=10) or ($a>=20). That is the else is obeyed when $a is less than or equal to 10 or greater than or equal to 20. The surprise is in the change from and to or in addition to the change to the inequalities.
The default
Now that you are aware that "else is hard" we can look at the default statement which essentially gives the switch an "else" or catch all option. If you end a switch with a default statement then if none of the case statements are obeyed the default is. For example:
switch ($a){
case 1:
instructions1;
break;
case 2:
instructions2;
break;
case 3:
instructions3;
break;
case 4:
instructions4;
break;
default:
defaultinstructions;
break;
}
You can see that the default instructions are only obeyed if none of the other conditions hold - that is if $a isn't equal to 1, 2, 3 or 4.As with all "else" type of constructions you should ask yourself what the condition is that causes the default statement to be obeyed? The answer is that the condition that is true when the default instructions are obeyed is$a<1 or $a>4.
elseif
It can be difficult to work out when an else or a default is going to be obeyed but there is a conditional instruction that is even tougher to get right - the elseif.The elseif can be places within an if statement in the same way as an else but it can include a condition that has to be true before its instructions are obeyed. You can have as many additional elseifs within a single if and have a final else to deal with anything that doesn't satisfy any of the conditions.
The idea is that you can use the elseif to place additional conditions on the else part of the if statement. For example
$a=3;
if($a==1){
echo("the value is one");
}elseif($a==2){
echo("the value is two");
}elseif($a==3){
echo("the value is three");
}else{
echo("the value is none of the above");
}
In this case the first echo is obeyed if $a is one. If this isn't the case then the elseif is evaluated and its echo statement is only obeyed if $a isn't one but is equal to two. Similarly the third echo statement is only obeyed if a$ isn't one or two but is equal to three. The final echo is only obeyed if a$ isn't one, two or three.
You can see that the elseif gives us an alternative way to implement a switch but usually when an if statement is easily reducible to a switch then it is better to use a switch. The real power and so danger of the elseif occurs when the conditions are such that they aren't mutually exclusive - in the previous example $a could only be one of the values specified. Consider the following small modification on the previous example:
$a=1;
$b=2;
$c=3;
if($a==1){
echo("the value of a is one");
}elseif($b==2){
echo("the value of b is two");
}elseif($c==3){
echo("the value of c is three");
}else{
echo("what is the condition?");
}
What is printed? The answer is that the first echo is obeyed because $a is one and the else parts of the if statement aren't even considered because the if condition is true.However if a was a value other than one then what would be printed would depend on the value of $b or $c. Notice that only one of the messages would ever appear because as soon as conditionevaluates to true the following elseifs or else are skipped.Now answer the final question - what is the condition that is satisfied for the echo belonging to the else to be obeyed? The answer is that $a has to be something other than one, $b has to be something other than 2 and $c has to be something other than 3 i.e. ($a!=1) and ($b!=2) and ($c!=3) has to be true.
In general when you are reading or trying to understand a complicated if-elseif-else construction always remember that for the if part to be obeyed the first condition has to be true. For the first elseif to be obeyed the first condition has to be false and the second condition true. For the second else if the first two conditions have to be false and the third has to be true and so on down to the final else for which all of the conditions have to be false.
If the else is hard the elseif can be very hard. Building complicated if statements is error prone but sometimes there is no choice. Always try to create the if statement or the switch that best conveys your meaning and always check that the elseif, else or default conditions are what you expect.