PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

declare> <continue
Last updated: Fri, 10 Oct 2008

view this page in

switch

switch文は、同じ式を用いてIF文を並べたのに似ています。 同じ変数を異なる値と比較し、値に応じて異なったコードを実行したいと 思うことがしばしばあるかと思います。 switch文は、まさにこのためにあるのです。

注意: 他の言語とは違って、 continue命令は switchにも適用され、breakと同じ動作をします。 ループの内部でswitchを使用しており、 外側のループの処理を続行させたい場合には、continue 2 を使用してください。

注意: switch/case が行うのは、 緩やかな比較 であることに注意しましょう。

次の二つの例は、同じことを二つの異なった方法で書いたものです。 一つは、if文を、もう一つはswitch 文を使っています。

例1 switch構造

<?php
if ($i == 0) {
   echo 
"iは0に等しい";
}
if (
$i == 1) {
   echo 
"iは1に等しい";
}
if (
$i == 2) {
   echo 
"iは2に等しい";
}

switch (
$i) {
    case 
0:
        echo 
"iは0に等しい";
        break;
    case 
1:
        echo 
"iは1に等しい";
        break;
    case 
2:
        echo 
"iは2に等しい";
        break;
}
?>

例2 switch構造では文字列を使用できる

<?php
switch ($i) {
case 
"apple":
    echo 
"i is apple";
    break;
case 
"bar":
    echo 
"i is bar";
    break;
case 
"cake":
    echo 
"i is cake";
    break;
}
?>

失敗を避けるためにswitch文がどのように実行されるのかを 理解することが重要です。 switch文は、行毎に実行されます。 (実際には、文毎に実行されます。)初めは、何も実行しません。 switch式の値と一致する値を有する case文が見つけられたときに初めてPHにより 命令の実行が行われます。 PHPはswitchブロックの終わりまたは最初の break文まで実行を続けます。 CASE文の終わりにbreak文を書かない場合は、PHPは 次のCASE文を実行しつづけます。例えば、

<?php
switch ($i) {
case 
0:
    echo 
"iは0に等しい";
case 
1:
    echo 
"iは1に等しい";
case 
2:
    echo 
"iは2に等しい";
}
?>

ここで、$iが0に等しい場合は、PHPは全ての echo 文を出力してしまいます! $iが1の場合、PHPは最後の二つの echo 文を出力します。 $iが2に等しい場合のみ、'期待した'動作をし、 'iは2に等しい'と表示します。 このため (ある種の状況下では、BREAKを付加することを避けたいと 思うかもしれませんが)、 break文を忘れないようにすることが重要です。

switch文では、条件は1度だけ評価され、 その結果が各case文と比較されます。 elseif文では、条件は、再度評価されます。 使用する条件が単純な比較処理よりも複雑な処理を行ったり、 重い繰り返し処理を行う場合、switchの方が より処理が速い可能性があります。

caseに付随する文は、空とすることが可能です。 この場合、次のcaseに付随する文に制御が移行します。

<?php
switch ($i) {
case 
0:
case 
1:
case 
2:
   echo 
"iは3より小さいですが負ではありません";
   break;
case 
3:
   echo 
"iは3です";
}
?>

default は、case 文の特別な場合です。これは他の全ての case にマッチしない場合に実行されます。例を以下に示します。

<?php
switch ($i) {
case 
0:
   echo 
"iは0に等しい";
   break;
case 
1:
   echo 
"iは1に等しい";
   break;
case 
2:
   echo 
"iは2に等しい";
   break;
default:
   echo 
"iは0,1,2に等しくない";
}
?>

case式は、スカラー型に式を評価する 任意の式、つまり、整数、浮動小数点、文字列とすることができます。 配列又はオブジェクトは、単純な型にキャストされていない限り 使用することができません。

switch文の制御構造に関する別の構文がサポートされています。 詳細は、 制御構造に関する別の構文を参照ください。

<?php
switch ($i):
case 
0:
   echo 
"iは0に等しい";
   break;
case 
1:
   echo 
"iは1に等しい";
   break;
case 
2:
   echo 
"iは2に等しい";
   break;
default:
   echo 
"iは0でも1でも2でもない";
endswitch;
?>
?>

case の最後はコロンではなくセミコロンとすることもできます。たとえば次のようになります。

<?php
switch($beer)
{
    case 
'ツボルグ';
    case 
'カールスバーグ';
    case 
'ハイネケン';
        echo 
'いいっすねぇ';
    break;
    default;
        echo 
'ほかのを選んでみませんか?';
    break;
}
?>



declare> <continue
Last updated: Fri, 10 Oct 2008
 
add a note add a note User Contributed Notes
switch
mar dot czapla at gmail dot com
11-Oct-2008 08: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
?>
cretz
01-Oct-2008 10: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!
mitchell/[.]/cain/[at]/gmail/[.]/com
11-Sep-2008 10: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//
mmxg at shaw dot ca
01-Jul-2008 06: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.
johan at dotco dot net
07-May-2008 10: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
    ;
jphansen at uga dot edu
12-Apr-2008 04: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;
}
?>
lko at netuse dot de
08-Apr-2008 01: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
Hayley Watson
25-Oct-2007 07: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
stever at ashomecare dot com
08-Sep-2007 02: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.
fteng1 at gmail dot com
04-Aug-2007 11: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";
juraj5
22-Jul-2007 05: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)
usera$ at example dot com
19-Jul-2007 03: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.
Drake
16-Jul-2007 03: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.
2mareks (at) gmail (dot) com
30-Nov-2006 10: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...
 
   
}
  }
?>
28-Oct-2006 08:29
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';
    }
sneskid at hotmail dot com
23-Oct-2006 09: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.
mdirks at gulfstreamcoach dot com
14-Sep-2006 12: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.
scott at firefallpro dot com
22-Dec-2005 07: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.
jonybd at yahoo dot com
28-Jun-2005 10: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;
    }
}
dohpaz at kennethpaul dot com
05-Jun-2005 08: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.
ant at loadtrax dot com
25-Mar-2005 04: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;
?>
Bruno Feu
23-Mar-2005 08: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";
}
?>
ach aat bitfabrik doot de
14-Mar-2005 10: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.
gregory dot mccoy at pleasedontspam dot cafeoui dot net
14-Mar-2005 04: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?
rdoggett at oz dot net
20-Jan-2005 12: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.
Derek Ethier
23-Dec-2004 06: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.
Bachsau
20-Dec-2004 11: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!!!
pentek_imre at mailbox dot hu
23-Oct-2004 09: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
tom AT csbanana DOT com
12-Oct-2004 03: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.
manicdepressive at mindless dot com
22-Apr-2004 09: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!
ezekiel at superquenelles dot com
26-Mar-2004 12: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.
php dot net dot 1 at yogelements dot com
20-Jan-2004 05: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
?>
gmgiles at pacbell dot net
19-Jan-2004 08: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.]
phpmanual at nos-pam dot sadlittleboy dot com
11-Jan-2004 12: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.
jon
09-Dec-2003 07: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...
havar at henriksen dot nu
15-Sep-2003 06: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;
}
?>
(cgibbard) student math uwaterloo ca
10-Aug-2003 07: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.
bishop
14-Jul-2003 05: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.
shawn at evilest dot net
04-May-2003 07: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;
                                }
                           }
                    }
                }
        }
    }
?>
i luv spam
26-Apr-2003 04: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.
jason at devnetwork dot net
24-Mar-2003 09: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.
kriek at jonkriek dot com
05-Mar-2003 01: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);
?>
jemore at m6net dotdot fr
14-Feb-2003 11: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;
      elseif (
$a === 'abc2') $nb += 3;
?>
because the '===' (3 equals signs) compare value without type conversion. Using a if/elseif/elseif structure instead of switch/case/case can be 2 times faster (I have made a test)
rmunn at pobox dot com
24-Jan-2003 06:21
In answer to njones at fredesign dot com, what you're seeing is the way the switch statement is supposed to work. The switch statement evaluates the cases, top to bottom, until it finds the first one that matches the value being switch()ed on. So, for example, if you had:

<?php
switch(2) {
case
1: echo "One\n"; break;
case
2: echo "Two\n"; break;
case
3: echo "Three\n"; break;
case
2: echo "Two again\n"; break;
}
?>

Only "Two" would get echoed. "Two again" would NOT get echoed, because once the first case matches, the rest of them do NOT get evaluated. As soon as a matching case is found, the statements starting at that case get executed until the first break, then control flows out the bottom of the switch block.
theonly dot mcseven at gmx dot net
19-Jan-2003 03:44
working a bit around with it I found out that it is not possible to
compare the variable with two different values in one step like this
(system running a w2k server, apache2.0.43 & php430):

<?php
switch ($myvar) {
 case (
"foo" || "bar"): //do something
 
break;
 case (
"other"): //do another thing
 
break;
 default:
}
?>

rather use:

<?php
switch ($myvar) {
 case (
"foo"):
 case (
"bar"): //do something
 
break;
 case (
"other"): //do another thing
 
break;
 default:
}
?>
turk162 at ALLSPAM_hotmail dot com
03-Dec-2002 11:55
On PHP V4.2.1, running on IIS5 as a CGI, I found an anomaly with how SWITCH handled strings.  I've heard that this problem doesn't exist on V4.2.3 on Apache.

This snippet took the wrong branch:

<?PHP
$wonum
= '20010E0';
SWITCH (
$wonum):
   CASE
'20010D0';
      ECHO
"<BR>Branching at D with wonum: " . $wonum;
      BREAK;
   CASE
'20010E0';
      ECHO
"<BR>Branching at E with wonum: " . $wonum;
      BREAK;
ENDSWITCH;
?>

Type casting with $wonum = (STRING) '20010E0'; didn't help.
Changing the order of the CASEs made no difference (it shouldn't, but...)

What did work was using MD5 to force a string comparison:

<?PHP
$wonum
= MD5('20010E0');
SWITCH (
$wonum):
   CASE
MD5('20010D0');
      ECHO
"<BR>Branching at D with wonum: " . $wonum;
      BREAK;
   CASE
MD5('20010E0');
      ECHO
"<BR>Branching at E with wonum: " . $wonum;
      BREAK;
ENDSWITCH;
?>

Moral: test test test
hexa at h3xa dot com
14-Nov-2002 02:55
this is a simple function that returns a random string and uses
switch to determine what kind of string you want.
function r( [string prefix][,int type,][,int chars] );

type = 1 -> only numbers
type = 2 -> only letters
type = 3 -> both

<?php
function r($prefixo = "",$tipo = 3,$numcaracteres = 10) {
    switch (
$tipo) {
        case
1:
            for (
$x = 1; $x <= $numcaracteres; $x++) {
               
$rnum .= chr(rand(48,57));
            }
            return
$prefixo . $rnum;
            break;
        case
2:
            for (
$x = 1; $x <= $numcaracteres; $x++) {
                if (
rand(1,2) == 1) { $rletras <