Example of default NOT included as the last item
switch(5) {
case 1:
echo "1";
break;
case 2:
default:
echo "2, default";
break;
case 3;
echo "3";
break;
}
Outputs '2,default'
very useful if you want your cases to be presented in a logical order in the code (as in, not saying case 1, case 3, case 2/default) and your cases are very long so you do not want to repeat the entire case code at the bottom for the default
Hamy
switch
The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for.
Замечание: Note that unlike some other languages, the continue statement applies to switch and acts similar to break. If you have a switch inside a loop and wish to continue to the next iteration of the outer loop, use continue 2.
Замечание: Note that switch/case does loose comparision.
The following two examples are two different ways to write the same thing, one using a series of if and elseif statements, and the other using the switch statement:
Пример #1 switch structure
<?php
if ($i == 0) {
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
}
?>
Пример #2 switch structure allows usage of strings
<?php
switch ($i) {
case "apple":
echo "i is apple";
break;
case "bar":
echo "i is bar";
break;
case "cake":
echo "i is cake";
break;
}
?>
It is important to understand how the switch statement is executed in order to avoid mistakes. The switch statement executes line by line (actually, statement by statement). In the beginning, no code is executed. Only when a case statement is found with a value that matches the value of the switch expression does PHP begin to execute the statements. PHP continues to execute the statements until the end of the switch block, or the first time it sees a break statement. If you don't write a break statement at the end of a case's statement list, PHP will go on executing the statements of the following case. For example:
<?php
switch ($i) {
case 0:
echo "i equals 0";
case 1:
echo "i equals 1";
case 2:
echo "i equals 2";
}
?>
Here, if $i is equal to 0, PHP would execute all of the echo statements! If $i is equal to 1, PHP would execute the last two echo statements. You would get the expected behavior ('i equals 2' would be displayed) only if $i is equal to 2. Thus, it is important not to forget break statements (even though you may want to avoid supplying them on purpose under certain circumstances).
In a switch statement, the condition is evaluated only once and the result is compared to each case statement. In an elseif statement, the condition is evaluated again. If your condition is more complicated than a simple compare and/or is in a tight loop, a switch may be faster.
The statement list for a case can also be empty, which simply passes control into the statement list for the next case.
<?php
switch ($i) {
case 0:
case 1:
case 2:
echo "i is less than 3 but not negative";
break;
case 3:
echo "i is 3";
}
?>
A special case is the default case. This case matches anything that wasn't matched by the other cases. For example:
<?php
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
}
?>
The case expression may be any expression that evaluates to a simple type, that is, integer or floating-point numbers and strings. Arrays or objects cannot be used here unless they are dereferenced to a simple type.
The alternative syntax for control structures is supported with switches. For more information, see Alternative syntax for control structures.
<?php
switch ($i):
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
endswitch;
?>
Its possible to use a semicolon instead of a colon after a case like:
<?php
switch($beer)
{
case 'tuborg';
case 'carlsberg';
case 'heineken';
echo 'Good choice';
break;
default;
echo 'Please make a new selection...';
break;
}
?>
switch
02-Jan-2009 08:32
12-Dec-2008 10:59
in case of multiple switch is needed this may also work.
<?php
switch (true)
{
case ($full_datum_auto==NULL and $full_datum_rev==NULL):
$datemessage = "both NULL";
break;
case ($full_datum_auto==NULL and $full_datum_rev!=NULL):
$datemessage = "REVISED";
break;
case ($full_datum_auto!=NULL and $full_datum_rev==NULL):
$datemessage = "AUTO";
break;
case ($full_datum_auto!=NULL and $full_datum_rev!=NULL):
if ($full_datum_rev > $full_datum_auto)
{
$datemessage = "AUTO and REVISED, but REVISED is bigger";
}
elseif ($full_datum_rev == $full_datum_auto)
{
$datemessage = "both equal";
}
else
{
$datemessage = "AUTO and REVISED, but AUTO is bigger";
}
break;
default :
$datemessage = "default filter is reached";
break;
}
?>
09-Dec-2008 05:06
As follow-up to ben dot lancaster at holler dot co dot uk's post:
'continue' ends the switch, not the case, just as it would with any other flow control. Think of it as putting the execution pointer right before the ending accolade (that is, the }) because that is essentially what happens. In the case of a for loop, this would cause the iteration clause to execute, and if applicable, the loop to begin again. However, switches do not loop, which is why (as noted above, in the manual!) a continue statement essentially acts as a break when within a switch.
10-Nov-2008 10:32
Just a word of warning about using switch don't try and compare variables that contain numbers with strings like so:
<?php
$i=0;
switch($i)
{
case 'TEST': print "Test";break;
case 0: print "0";break;
}
?>
The output will be: Test and not 0.
17-Oct-2008 12:46
Following on from bensphpnetemail at supernaut dot org's post, it would seem that 'continue' doesn't really continue at all. Consider the following:
<?php
$foo = 'bar';
$bar = true;
switch($foo)
{
case 'bar':
if($bar)
{
continue;
}
echo '$bar is false';
break;
case 'bar':
case 'foo':
echo '$bar is true, or $foo is foo';
break;
default:
echo "You shouldnt ever get here";
break;
}
?>
I would expect the above to output "$bar is true, or $foo is foo", but it doesn't output anything. The continue statement acts as a break and stops evaluating the rest of the matching cases.
Instead, you should issue a 'break' statement conditionally to achieve the desired result.
10-Oct-2008 11:17
<?php
/* script 1 */
$foo = "not a number";
switch(false)
{
case "1": { $foo = "1"; break; }
case "2": { $foo = "2"; break; }
default: { $foo = "0"; }
}
echo $foo; // will produce "not a number"
/* script 2 */
$foo = "not a number";
$arr = array("not a number"); // 1 element only !
switch($arr[1]) // element $foo[1] doesn't defined
{
case "1": { $foo = "1"; break; }
case "2": { $foo = "2"; break; }
default: { $foo = "0"; }
}
echo $foo; // will produce "not a number" ( not 0 ! )
/* script 3 */
$foo = "not a number";
$arr = array("not a number"); // 1 element only !
switch($arr[1]?$arr[1]:"1") // element $foo[1] doesn't defined
{
case "1": { $foo = "1"; break; }
case "2": { $foo = "2"; break; }
default: { $foo = "0"; }
}
echo $foo;
// will produce :
// 1 if $arr[1] isn't set
// 1 if $arr[1]=1
// 2 if $arr[1]=2
// 0 if none of above
?>
01-Oct-2008 02:56
Haven't seen it mentioned here, but at least in my version (PHP 5.2.5) and I'm sure all of PHP 5, the switch statement is a great way to check type safe enumerates that are otherwise missing in the PHP language. Example:
<?php
class WannabeEnum {
/**
* @var WannabeEnum
*/
public static $FOO;
/**
* @var WannabeEnum
*/
public static $BAR;
/**
* @var WannabeEnum
*/
public static $FOOBAR;
private $_ordinal;
public function __construct($ordinal) {
$this->_ordinal = $ordinal;
}
}
WannabeEnum::$FOO = new WannabeEnum(1);
WannabeEnum::$BAR = new WannabeEnum(2);
WannabeEnum::$FOOBAR = new WannabeEnum(3);
function testSwitch(WannabeEnum $wannabeEnum) {
switch($wannabeEnum) {
case WannabeEnum::$FOO:
echo('Foo!' . PHP_EOL);
break;
case WannabeEnum::$BAR:
echo('Bar!' . PHP_EOL);
break;
default:
echo('Default!' . PHP_EOL);
}
}
testSwitch(WannabeEnum::$FOO);
testSwitch(WannabeEnum::$FOOBAR);
?>
Outputs:
Foo!
Default!
Don't forget it uses loose comparisons!
11-Sep-2008 02:52
double switch
<?php
$foo = 2;
$bar = 11;
switch ($foo) {
case 1:
echo 'foo is 1//';
break;
case 2:
echo 'foo is 2//';
switch ($bar) {
case 10:
echo 'bar is 10//';
break;
case 11:
echo 'bar is 11//';
break;
default:
echo 'bar is neither 10 or 11//';
break;
}
break;
default:
echo 'foo is neither 1 or 2//';
break;
}
?>
output:
foo is 2//bar is 11//
01-Jul-2008 10:30
In reply to lko at netuse dot de
Just so others know whom may not, that's because PHP does automatic type conversion if a string is evaluated as an integer (it sees the 2 in '2string' so when compared like if ('2string' == 2), PHP sees if (2 == 2) ).
I just tested it, but if you go:
<?php
$string="2string";
switch($string)
{
case (string) 1:
echo "this is 1";
break;
case (string) 2:
echo "this is 2";
break;
case '2string':
echo "this is a string";
break;
}
?>
The output will be "this is a string" and if you change $string to "2" it will again be "this is 2".
Just in case that may help anyone who may run into that problem.
07-May-2008 02:51
A switch statement with more than one default is valid in PHP 5.2.6. However, only the last default gets executed as the default clause.
<?php
switch(9) {
case 1:
echo 1 . "\n";
case 2:
echo 2 . "\n";
break;
case 3:
echo 3 . "\n";
case 4:
echo 4 . "\n";
case 5:
echo 5 . "\n";
default:
echo 6 . "\n";
default:
echo 7 . "\n";
default:
echo 8 . "\n";
}
// Outputs:
// 8
//
// Did you expect 6 and 7 to print too?
switch(3) {
case 1:
echo 1 . "\n";
case 2:
echo 2 . "\n";
break;
case 3:
echo 3 . "\n";
case 4:
echo 4 . "\n";
case 5:
echo 5 . "\n";
default:
echo 6 . "\n";
default:
echo 7 . "\n";
default:
echo 8 . "\n";
}
// Outputs:
// 3
// 4
// 5
// 6
// 7
// 8
?>
The problem (if it is one), is in the recursive definition of the default clause of a case_list in the parser.
zend_language_parser.y
// Many default clauses allowed.
case_list:
/* empty */
| case_list T_CASE expr case_separator inner_statement_list
| case_list T_DEFAULT case_separator inner_statement_list
;
// Only one default clause allowed.
case_list:
/* empty */
| case_list T_CASE expr case_separator inner_statement_list
| T_DEFAULT case_separator inner_statement_list
;
11-Apr-2008 08:33
An easy mistake some programmers from other languages might make is delimiting conditions for a case block by a comma:
<?
$val = "x";
switch ($val) {
case "x", "y", "z":
echo "Case is x, y or z";
break;
}
?>
Instead, in PHP this is accomplished by using the "case" identifier for each condition:
<?
$val = "x";
switch ($val) {
case "x":
case "y":
case "z":
echo "Case is x, y or z";
break;
}
?>
07-Apr-2008 05:51
Attention if you have mixed types of value in one switch statemet it can make you some trouble
<?php
$string="2string";
switch($string)
{
case 1:
echo "this is 1";
break;
case 2:
echo "this is 2";
break;
case '2string':
echo "this is a string";
break;
}
?>
The swich-statement will halt on 'case 2'
Answer: this is 2
24-Oct-2007 11:02
Something not mentioned in the documentation itself, and only touched on momentarily in these notes, is that the default: case need not be the last clause in the switch.
<?php
for($i=0; $i<8; ++$i)
{
echo $i,"\t";
switch($i)
{
case 1: echo "One"; break;
case 2:
default: echo "Thingy"; break;
case 3:
case 4: echo "Three or Four"; break;
case 5: echo "Five"; break;
}
echo "\n";
}
?>
Outputs what you'd expect, namely
0 Thingy
1 One
2 Thingy
3 Three or Four
4 Three or Four
5 Five
6 Thingy
7 Thingy
with case 2 and the default both producing the same result ("Thingy"); strictly speaking, the case 2 clause is completely empty and control just falls straight through. The same result could have been achieved with
<?php
switch($i)
{
case 1: echo "One"; break;
case 3:
case 4: echo "Three or Four"; break;
case 5: echo "Five"; break;
default: echo "Thingy"; break;
}
?>
But if "case 2" represented a fairly common case (other than "everything else"), then it would be better to declare it explicitly, not only because it saves time by not having to test EVERY other case first (in the current example, PHP finds 'case 2' in the first switch in two tests, but in the second switch it has to make four tests before giving up and going with the default) but also because someone (perhaps yourself in a few months' time) will be reading the code and expecting to see it handled. Listing it explicitly aids comprehension
07-Sep-2007 06:11
Just a reminder: there may be easier ways to manipulate _long_ lists of data instead of using switches.
function getChineseZodiac($year){
// Chinese Zodiac Animals
$animals = Array
(
'Monkey', // Years 0, 12, 1200, 2004...
'Rooster',
'Dog',
'Boar',
'Rat',
'Ox',
'Tiger',
'Rabit',
'Dragon',
'Snake',
'Horse',
'Lamb'
);
// Number of animals and years in a calendar rotation
$numAnimals = count($animals);
// Years left until full rotation of calender
$yearOffset= round($year) % $numAnimals;
return $animals[$yearOffset];
}
Of course this is a really generic function, we're just finding how many years away from a full 12 year rotation the current year is.
04-Aug-2007 03:46
Here's a lazy way of doing an comparison where multiple conditions equal the same result using arrays.
if (in_array($year,array(1948, 1960, 1972, 1984, 1996, 2008)))
echo "Rat";
elseif (in_array($year,array(1949, 1961, 1973, 1985, 1997, 2009)))
echo "Ox";
elseif (in_array($year,array(1950, 1962, 1974, 1986, 1998, 2010)))
echo "Tiger";
elseif (in_array($year,array(1951, 1963, 1975, 1987, 1999, 2011)))
echo "Rabbit";
elseif (in_array($year,array(1952, 1964, 1976, 1988, 2000, 2012)))
echo "Dragon";
elseif (in_array($year,array(1941, 1953, 1965, 1977, 1989, 2001)))
echo "Snake";
elseif (in_array($year,array(1942, 1954, 1966, 1978, 1990, 2002)))
echo "Horse";
elseif (in_array($year,array(1943, 1955, 1967, 1979, 1991, 2003)))
echo "Lamb";
elseif (in_array($year,array(1944, 1956, 1968, 1980, 1992, 2004)))
echo "Monkey";
elseif (in_array($year,array(1945, 1957, 1969, 1981, 1993, 2005)))
echo "Rooster";
elseif (in_array($year,array(1946, 1958, 1970, 1982, 1994, 2006)))
echo "Dog";
elseif (in_array($year,array(1947, 1959, 1971, 1983, 1995, 2007)))
echo "Boar";
21-Jul-2007 09:00
In response to 'i luv spam',
when you enter 07, you tell PHP to interpret a number as an octal number (much like '0x' for hex numbers). Octal numbering system uses only 8 digits, i.e. 0-7. http://en.wikipedia.org/wiki/Octal
The number 8 does not exist in octal numbering system. The comparison works because the octal numbers 0 to 7 have identical counterparts in decimal system.
So, in order to get a number compared as decimal 8, you would have to enter 010 in the case.
BTW this behavior obviously isn't specific to switch, it's a part of PHP.
(I personally stumbled into this when trying to make my code nicely indented while declaring an array)
18-Jul-2007 07:35
A note as to how the comparisons of case values to the switch value are being made would be useful, since it appears, the comparison operator === is not available, only ==. That means, according to the example given, in
switch($a)
...
case 0
statement-0
case FALSE
statment-1
case NULL
statement-2
...
both statement-1 and statement-2 cannot be executed, no matter what the value of $a is, including FALSE.
16-Jul-2007 07:51
Also,
when using switch for mode selecting on websites like:
switch($_GET['mode']) {
case "gallery":
//code
break;
case "news":
//code
break;
case "stuff":
//code
break;
default, etc etc
}
Will NOT trigger the string == 0 bug, because $_GET automatically parse anything passed to them as strings.
(same applies for all browser variables: SESSION, POST etc)
so passing:
mode=0
into the address bar is the same as:
$_GET['mode'] = "0"; //not $_GET['mode'] = 0;
thought it may help.
30-Nov-2006 12:03
In reply to earlier comment, "switch"- I found this to be one of the best ways to interpret 'actions'. Simply create a new instance of Handler_action before including any content source files. This is a highly stripped version of the class.
The real one I created handles (and secures) input for $_GET and $_POST, creates a 'permission' array that only allows certain actions to be called by non-admins, and creates handy little diagnostic messages that can be displayed upon redirecting.
On that note, the beauty in this class really shines in the simple redirect. You wont be left with ugly URLs like, "http://www.domain.com/path/to/script.php?action=blah&var1=123". Rather, you will be left with something like "http://www.domain.com/path/to/script.php"- helps protect some of the site by not showing any vulnerabilities in URLs.
Also, this class keeps all actions organized neatly by directly passing $_GET vars to the actions through function parameters.
<?php
class Handler_action {
function __construct( ){
//Add code here to secure attacks through $_GET or use $_POST
$action = $_GET["action"];
//$actions_index conventions:
//'action_name' => array( 'arg1', 'arg2', 'etc', ['/redirect/to/path' | NULL ] )
$actions_index = array(
'create' => array( $_GET['newVar1'], $_GET['newVar2'], '/home.php' ),
'edit' => array( $_GET['id'], $_GET['otherVar'], '/home.php' ),
'delete' => array( $_GET['id'], '/other_script.php' )
);
if( $action && array_key_exists( $action, $actions_index ) ){
$redirect_path = array_pop( $actions_index[$action] );
call_user_func_array( array( &$this, $action ), $actions_index[$action] );
if( $redirect_path )
header( "Location: http://www.domain.com{$redirect_path}" );
}
}
//being defining actions now
function create( $new_var1, $new_var2 ){
//code...
}
function edit( $id, $other_var ){
//code...
}
function delete( $id ){
//code...
}
}
?>
I could have used a swich for this, but I found that using the array was much faster.
$action = $_GET['action'];
$pages = array
(
'edit' => './edit.php',
'search' => './search.php'
);
if(strlen($pages[$action]) > 0)
{
require $pages[$action];
}
else
{
require './default.php';
}
23-Oct-2006 01:38
In regard to what dohpaz at kennethpaul dot com wrote.
If you ever have time you may want to test out having a premade associative array with the required elements eaqualing the needed value. Then assign the value based on the array element.
in dohpaz's month example it would look like this:
<?php
$arr_month = array(
'January' => 1,
'February' => 2,
'March' => 3,
'April' => 4,
'May' => 5,
'June' => 6,
'July' => 7,
'August' => 8,
'September' => 9,
'October' => 10,
'November' => 11,
'December' => 12);
foreach($arr_month as $k => $v) {$arr_month[substr($k,0,3)] = $v;} // autogen a 3 letter version
//note that the overall size will be 23 because May will only exist once
$month = 'Jan';
$month = $arr_months[$month];
echo $month; // outputs: 1
?>
It beats a switch in this case.
I did some benchmarking.
The array system is faster than the switch system.
Here were my average time results of 1000 itterations of assigning the numeric value to the month.
The value was randomized between each itteration (this was not added to the benchmark value), so each method was simulated with various data to stress different points.
array:
'avg' => 1.09958648682E-6
switch:
'avg' => 4.32157516479E-6
switch (true):
'avg' => 6.90913200378E-6
Contrary to what dohpaz suggested I found that a normal switch was faster than a switch(true) version.
I repeated these test several times to take into acount server load variations. The ratios were always consistent.
The array way is notably faster.
13-Sep-2006 04:09
In response to scott at firefallpro dot com:
"Also note that even though a conditional statement needs to be explicitly set in each case to gain expected behavior, the switch can still execute faster then an "if/elseif/else" block because PHP will not continue to evaluate conditions once a case has been satisfied."
This is not accurate as far as the documentation would say. PHP does not (or at the very least should not) continue to evaluate other "if/elseif/else" statements () on the same level once a true statement is found. It will (should) "short-circuit" to after the else block in the same depth-level, once it has finished executing all the code in it's block naturally.
Where the switch statement wins out over an "if/elseif/else" block is it's ability to "fall though" to instructions in following cases until a break is encountered. Coding something similiar using "if/elseif/else" statements could get really messy and buggy really fast depending on the switch statement.
22-Dec-2005 09:01
It's has already been mentioned indirectly in a few posts, but it is important to realize that switch statements evaluate each case with the "==" operator by default. This can lead to unexpected results when comparing strings to integers, because PHP will convert the string to an integer. In many cases this means a string can be equivalent to the integer 0.
Example:
<?php
$x = 0;
switch($x) {
case "a":
echo "a";
break;
case "b":
echo "b";
break;
default
echo "default";
}
?>
The result will be an "a" echoed out. What PHP does in this instance, is once it realizes that it's attempting to compare string ("a") to an integer (0), it converts "a" into an integer which ends up satisfying the first case.
The rules for string conversion into integers is available at:
http://us3.php.net/manual/en/language.types.string.php
The easiest way to combat this issue is to force type comparison by using the "===" operator. This makes PHP forego the string to integer conversion.
Example:
<?php
switch(true) {
case $x === "a":
echo "a";
break;
case $x === "b":
echo "b";
break;
default
echo "default";
}
?>
Or the switch input can be type-casted to always be a string, etc.
Also note that even though a conditional statement needs to be explicitly set in each case to gain expected behavior, the switch can still execute faster then an "ifelse" block because PHP will not continue to evaluate conditions once a case has been satisfied.
28-Jun-2005 02:25
/*
Have one value need to deal with currency
- follow as example
*/
while ($row = mysql_fetch_array($v_Result,MYSQL_NUM)) {
$v_BAL = $row[1]/10000;
switch (TRUE){
case ($v_BAL <= 0): //less then 0 , -0
echo $v_BAL;
break;
case ($v_BAL <= 10 AND $v_BAL >= 1): //less then 10 and greater then 1
echo $v_BAL;
break;
default: //default
echo $v_BAL;
break;
}
}
05-Jun-2005 12:24
[Editor's note: Changed the second switch to make it work as intended.]
I haven't seen anything specifically pointing this out, but you can get a small performance increase in your code by re-structuring your complex switch statements.
For example, I was using the following switch to convert textual month names into their numerical counterparts from the Date header of email on my pop server:
switch ($month_name) {
case "Jan":
case "January":
$month = "1";
break;
...
}
Even just looping through 15 emails on the server, it would take upwards of around 9-10 seconds! So, I decided to shorten my switch statement to something like this:
switch (TRUE) {
case ($month_name == "Jan" || $month_name == "January"): $month = "1"; break;
...
}
Doing this I actually shaved 3 seconds from my script's execution time!!! I thuoght this was well worth noting for other coders out there who are looking to optimize their PHP code.
24-Mar-2005 06:01
This caught me out. The number '6' when compared with the string '6b' returns true. The solution is to either typecast the compare - ie, " switch ((string)$type): " or to make sure $type is a string (eg $type="6")
<?
$type=6;
switch ($type):
case "6b":
print "6b: ";
print $type;
break;
case "6":
print "6: ";
print $type;
break;
endswitch;
?>
22-Mar-2005 10:22
You can solve the problem by just writing the following piece of code:
<?php
$x = 18;
$y = 6;
switch ($x) {
case ($y * 4):
case (9 * 3):
echo "Member";
break;
default:
echo "Not a member";
}
?>
14-Mar-2005 12:21
So instead of writing the code shown below it would have to be like this:
<?php
$x = 18;
$y = 6;
switch ($x) {
case ((($y * 4) || (9 * 3))?$x:false):
echo "Member";
break;
default:
echo "Not a member";
}
?>
So now the case expression contains an if statement in simplified notation which either returns the value of $x if the expression is true (so the case matches) or false, if the expression was false (so the case does not match).
Be aware that it only works if $x never actually is "false" because then it would match in either case. So the "false" in the above code should always be any random value which is not a possible value for $x.
13-Mar-2005 06:07
In the post:
----------------------------------------------------
design at hyperoptix dot com
18-Feb-2004 12:46
Boolean logic does not work inside case statements:
<?php
$x = 18;
$y = 6;
switch ($x) {
case (($y * 4) || (9 * 3)):
echo "Member";
break;
default:
echo "Not a member";
}
?>
echoes "Member".
----------------------------------------------------
there were many responses but all seem to miss the point. You cannot mix apples and oranges. The "switch($x)" establishes that this "switch" statement will be a Relational syntax while the "case" qualifier uses a Logical syntax. There must be a match. Either change "switch($x)" to "switch(true)" or change "case(($y * 4) || (9 * 3)):" to resolve to a value.
The syntax of the original post is like a cop that says, "I want all of your answers to reflect truth. So, are you eighteen?" The respondent says, " 4 x 4 or 11 + 5". Need I say more?
19-Jan-2005 02:01
Here's an often overlooked way of doing (nearly) the same thing:
<?php
echo ($i == 0) ? "i is zero" :
(($i == 1) ? "i equals 1" :
(($i == 2) ? "i equals 2" : ""));
?>
This may be an idiomatic surprise at first. But the clean and concise code speaks for itself.
Beware; PHP seems to parse the ternary operator with a different precedence than other languages such as C or perl or javascript. This means PHP requires nested parenthesis around each nested group to avoid unexpected results. Even so, this construct is still very understandable and maintainable, compared to the equivalent switch or if statements.
22-Dec-2004 08:43
A word of caution around the order used for the case/default controls. I notice that a lot of people do not break; the default section and the following could lead to incorrect results when run.
$a = "lowercase";
switch ( $a ) {
default:
$a = strtoupper( $a );
print $a . "<br />";
case ( 'LOWERCASE' ):
print $a . "<br />";
break;
}
Result:
LOWERCASE
LOWERCASE
Placing a break; in the default control will result in:
LOWERCASE
.. as expected. Also, placing the default section at the bottom (as in an else control) will also display the correct result.
20-Dec-2004 01:52
Be carefull: If you want to test the return of a function, you have to use switch, because if you use 'if' and 'ifelse', your function will be executed every time again.
For example if use use the following construct:
if(file_get_contents('file.htm', 0) == 'typ1') {
// Do one thing
}
ifelse(file_get_contents('file.htm', 0) == 'typ2') {
// Do the second thing
}
ifelse(file_get_contents('file.htm', 0) == 'typ3') {
// Do the third thing
}
The file will be requested 3 times!!!
If you use the following:
switch (file_get_contents('file.htm', 0)) {
case 'typ1': // Do one thing
break;
case 'typ2': // Do the second thing
break;
case 'typ3': // Do the third thing
}
The file will be requested only once!!!
23-Oct-2004 01:25
Using select is like using == (instead of ===) in an if statement. Let's see an example:
<?php
function Describe($Q)
{
var_dump($Q);
echo ": ";
switch ($Q)
{
case "0":
echo "String zero";
break;
case 0:
echo "Integer zero";
break;
case NULL:
echo "NULL NULL";
break;
case FALSE:
echo "Boolean FALSE";
break;
case "":
echo "Empty string";
break;
default:
echo "Any other value";
break;
}
echo "<BR>\n";
}
Describe("0");
Describe(0);
Describe(NULL);
Describe(FALSE);
Describe("");
Describe(1);
?>
Output (PHP 5.0.1) is:
string(1) "0" : String zero
int(0) : String zero
NULL : Integer zero
bool(false) : String zero
string(0) "" : Integer zero
int(1) : Any other value
12-Oct-2004 07:18
If you're using switch() inside a function and you're returning a $var inside each case, you won't need to include break() as return() will end the execution of the switch and function.
22-Apr-2004 01:43
Be careful if distinguishing between NULL and (int)0. As implied in the above documentation, the case statements are equivalent to the '==' operator, not the '===' operator, so the following code did not work as i expected:
<?php
$mixed = 0;
switch($mixed){
case NULL: echo "NULL"; break;
case 0: echo "zero"; break;
default: echo "other"; break;
}
?>
Instead, I may use a chain of else-ifs. (On this page, kriek at jonkreik dot com states that "in most cases [a switch statement] is 15% faster [than an else-if chain]" but jemore at m6net dotdot fr claims that when using ===, if/elseif/elseif can be 2 times faster than a switch().)
Alternatively, if i prefer the appearance of the switch() statement I may use a trick like the one nospam at please dot com presents:
<?php
$mixed = 0;
switch(TRUE){
case (NULL===$mixed): //blah break;
case (0 ===$mixed): //etc. break;
}
?>
code till dawn! mark meves!
25-Mar-2004 02:40
In reply to Alex Fung :
The following code doesn't work :
<?php
$x = 18;
$y = 6;
switch ($x) {
case (($y * 4) || (9 * 3)):
echo "Member";
break;
default:
echo "Not a member";
}
?>
Why :
<design at hyperoptix dot com> want to test if $x == $y*4 or $x == 9*3 ($x == (($y*4)||(9*3))
However the case statement evaluate the value of (($y*4)||(9*3)) that is always true because 9*3=27 (!=0)
That's why this code always return true when $x != 0.
The correct code would be :
<?php
$x = 18;
$y = 6;
switch ($x) {
case (($y * 4)):
case ((9*3)):
echo "Member";
break;
default:
echo "Not a member";
}
?>
Boolean logic work inside case statement, you just need to know that the expression in the case statement is first evaluated then compared with the evaluated value in the switch statement.
20-Jan-2004 07:39
Declaring a variable (actually an array) as static w/in a switch{} spun my wool for a while:
don't:
<?
function ss() {
switch ("bug") {
case "bug" :
static $test = "xyz";
break;
default :
static $test = "abc";
}
echo $test;
}
ss(); //abc
?>
do:
<?
function tt() {
static $test;
switch ("fix") {
case "fix" :
$test = "xyz";
break;
default :
$test = "abc";
}
echo $test;
}
tt(); // xyz
?>
19-Jan-2004 10:07
Did you know that switch() and case() can also accomodate things like basic math calculations and counter incrementing? They do. In this example, I use a switch statement (which is inside of a while loop) to alternate the background color of a table row. It gives me a cool spool-printer-paper effect.
<?php
$rows_per_color = 5; // change bgcolor every 5 rows
switch($ctr++) {
case 0:
$bgcolor = "#ffffff";
break;
case ($rows_per_color):
$bgcolor = "#ff0000";
break;
case ($rows_per_color * 2):
$bgcolor = "#ffffff";
$ctr = 1;
break;
}
?>
As you can see, I increment $ctr by 1 in the switch() itself, and the final case() does a simple calculation. Simple, but powerful. [Remember, the above example is inside of a while() loop... each time it iterates, switch increments $ctr.]
10-Jan-2004 02:32
Regarding bishop's comment below, although using:
switch($bug === 0 ? '' : $bug) {
may work, ( and although I do like the ternary operator, :) it might be more intuitive/readable to use this instead:
switch( (string)$bug ) {
which typecasts the variable to a string to ensure that "0" will be handled correctly.
08-Dec-2003 09:48
In response to the entry by "kriek at jonkriek dot com", I think you would probably be better of doing this:
<?php
// ensure $_GET['go'] is set, an integer, and not 0
// then, set nav number; default to 1
$nav = ( isset($_GET['go']) && (intval($_GET['go']) == $_GET['go']) && $_GET['go'] ) ?
intval($_GET['go']) : 1;
// format navigation string and include
include(sprintf("Page%02d.php",$nav));
?>
... as oppposed to the switch setup you recommended, which is limited to the number of cases you specify...
14-Sep-2003 10:54
Remember, that you also could use functions in a switch.
For example, if you need to use regular expressions in a switch:
<?php
$browserName = 'mozilla';
switch ($browserName) {
case 'opera':
echo 'opera';
break;
case (preg_match("/Mozilla( Firebird)?|phoenix/i", $browserName)?$browserName:!$browserName):
echo "Mozilla or Mozilla Firebird";
break;
case 'konqueror':
echo 'Konqueror';
break;
default:
echo 'Default';
break;
}
?>
or you could just use a regular expression for everything:
<?php
$uri = 'http://www.example.com';
switch (true) {
case preg_match("/$http(s)?/i", $uri, $matches):
echo $uri . ' is an http/https uri...';
break;
case preg_match("/$ftp(s)?/i", $uri, $matches):
echo $uri . ' is an ftp/ftps uri...';
break;
default:
echo 'default';
break;
}
?>
10-Aug-2003 11:30
Just in reply to the comment about 2 digit numbers: something octal certainly is going on. Integer literals prefixed with a "0", like in C and several other languages, are treated as octal. Similarly, integer literals prefixed with "0x" are treated as hexadecimal. Seeing as this is the case, 08 and 09 are not valid integer literals. It turns out that php treats them as 0 (it would probably be better to fail with an error message, but it doesn't). Bottom line? Don't prefix numbers with 0 in code unless you mean octal. Format them as you print them with printf, like so: printf("%02u", $my_unsigned_int); or if you will, use sprintf to get a string representation rather than printing on stdout.
14-Jul-2003 09:26
As jason at devnetwork dot net and others have pointed out, using switch() when you wish to compare against strings can be dangerous:
<?php
$bug = 0;
switch ($bug) {
case 'fly':
echo 'flies buzz';
break;
case 'mantis':
echo 'mantes pray';
break;
default:
echo 'swat, splat, you are dead';
break;
}
?>
Will print "flies buzz", NOT "swat, splat, you are dead".
Remember PHP says that 'fly' == 0, or in general string == 0 is true.
Anyway, avoid that with:
<?php
$bug = 0;
switch ($bug === 0 ? '' : $bug) {
case 'fly':
echo 'flies buzz';
break;
case 'mantis':
echo 'mantes pray';
break;
default:
echo 'swat, splat, you are dead';
break;
}
?>
Prints out what you expect:
Swat
Splat
You are dead
P.S.: that's an empty string (single quote single quote), not a spurious double quote.
04-May-2003 11:50
You can also nest switch statements inside case statements:
<?php
// Set argument handlers
$argv = explode(",", urldecode(getenv('QUERY_STRING')));
$argc = array_shift($argv);
$argd = array_shift($argv);
$arge = array_shift($argv);
?>
// Begin switching
<?php
switch ($argc) {
case 'home': {
print('This is $argc, home case.');
break;
}
case 'subsection': {
switch ($argd) {
case 'links': {
switch($arge) {
case 'display': {
print('This is $arge, subsection,links,display case.');
break;
}
}
}
}
}
}
?>
25-Apr-2003 08:46
Noticed some odd switch behavior worth mentioning:
Switching on a variable set as $var="08" and forgetting the quotes within the case results in different behavior depending on the two digit number the variable is set to.
For "01" to "07", using a case like
case 01:
the case is triggered.
For "08" or "09" the case is skipped.
For "10" to "12" the case is triggered.
Looks like something octal may be going on.
Anyway, not a problem once the case is changed to:
case "08":
as it should have been from the start. Just odd.
24-Mar-2003 11:51
It should be pointed out that this:
<?php
$var = 0;
switch ( $var )
{
case "something":
$foo = "Broken";
break;
default:
$foo = "Okay";
break;
}
echo $foo;
?>
Will print out "Broken". It's not broken, because in PHP, when an Integer and a String are compared, the string is == 0. So 0 == "something". However, this is not apparent. switch() does not do type checking.
05-Mar-2003 03:13
Nice, clean, template style navigation. In most cases it is fifteen percent faster to use switch/case/break instead of if/elseif/else. Of course this depends on your application and individual code results do very.
<?php
switch ($_GET['go']) {
case "1": $inc = 'Page01.php';
break;
case "2": $inc = 'Page02.php';
break;
case "3": $inc = 'Page03.php';
break;
case "4": $inc = 'Page04.php';
break;
default: $inc = 'Page01.php';
break;
}
include ($inc);
?>
14-Feb-2003 01:26
siwtch() made always a type conversion before comparing all the case value (PHP4.3.0), so the following statement
<?php
// $a = 'abc0' or 'abc1' or 'abc2', so this is a string
switch ($a)
{
case 'abc0' : $nb += 1; break;
case 'abc1' : $nb += 2; break;
case 'abc2' : $nb += 3; break;
}
?>
is slower than the following statement
<?
if ($a === 'abc0') $nb += 1;
elseif ($a === 'abc1') $nb += 2