6

The example below is an extráct from http://php.net/manual/de/control-structures.switch.php

<?php
$totaltime = 0;
switch ($totaltime) {

    case ($totaltime < 1):
        echo "That was fast!";
        break;

    case ($totaltime > 1):
        echo "Not fast!";
        break;

    case ($totaltime > 10):
        echo "That's slooooow";
        break;
}

?>

I expected the result as "That was fast." But actual result is "Not fast!". It would be great if some one can explain me why?

But if i add another case, case 0: echo "That was super fast!". Then it is echoing properly. i.e "That was super fast!". Please help me how to use conditional switch statement.

EDIT:-

Thanks all for your responses. I am able to overcome the above problem by modifyong switch($totaltime) to switch(1)

1
  • = Switch only evaluate once, you seems mis-used on it Commented Dec 21, 2010 at 11:31

6 Answers 6

9

case ($totaltime < 1): means 1 to PHP (that equation returns true)

case ($totaltime > 1): means 0 to PHP (that equation returns false)

Since $totaltime is 0, you get that output

In other words PHP compares $totaltime to the result of the comparisons.

EDIT regarding EDIT in OP:

You need to get rid of the switch()-statement. You only use it to easily compare against different values and not use additional expressions with it.

I mean what is wrong with

<?php
$totaltime = 0;

if ($totaltime < 1) {
    echo "That was fast!";
} else if ($totaltime > 10) {
    echo "That's slooooow";
} else if ($totaltime > 1) {
    echo "Not fast!";
}

?>

EDIT: please note that I switched the last two if-statements to make it really work.

Sign up to request clarification or add additional context in comments.

2 Comments

- There is no wrong at all. But i have close to 20 values for which i need to compare and display error. So i thought switch will make it more readbale instead of IF.
@lucky: but you do understand that it is much more readable with a set of if() statements? It would also mean less code resulting in less chances for a bug (that's more of a general rule, though).
2

You don't use conditionals in the case statements like that, not intuitively anyway. This is what's happening:

    case ($totaltime < 1):  // Evaluates to 1.  $totaltime is not 1, so no match.
    case ($totaltime > 1):  // Evaluates to 0.  $totaltime is 0, so match.

Essentially you're trying to use an else if construct as a switch construct, but the functionality isn't there. The conditionals don't evaluate in the way you're expecting (the way they would in an if block), they're just looking for the first case block which equals the value being tested in the switch block.

Comments

2

Hate to necro a post that's already answered but I am rather baffled no one touched on the switch(true) method.

There is no real world speed advantage of either method

In some cases the switch was faster, others the if was faster, but only by fractions of a microsecond (48.16 µs vs 49.11 µs switch faster than if).

EDIT

And now I see the OP did the same...

<?php
for ( $totaltime = 0; $totaltime < 11; $totaltime += 0.5 ) {
    switch ( true ) {
        case ( $totaltime < 1 ):
            echo $totaltime . " That was fast!\n";
            break;
        case ( $totaltime < 10 ):
            echo $totaltime . " Not fast!\n";
            break;
        default:
            echo $totaltime . " That's slooooow\n";
            break;
    }
}

Results: https://3v4l.org/d71lZ

0 That was fast!
0.5 That was fast!
1 Not fast!
1.5 Not fast!
2 Not fast!
2.5 Not fast!
3 Not fast!
3.5 Not fast!
4 Not fast!
4.5 Not fast!
5 Not fast!
5.5 Not fast!
6 Not fast!
6.5 Not fast!
7 Not fast!
7.5 Not fast!
8 Not fast!
8.5 Not fast!
9 Not fast!
9.5 Not fast!
10 That's slooooow
10.5 That's slooooow

Comments

1

It would almost seem that this is a bolean conversion issue.

The first case statement will evaluate to anything other than 0, so that will not hit.

But the second case statement will evaluate to false, which should be 0 which is equal to what you have set $totaltime to.

Comments

1

Lucky,

PHP switch is same as series of IF statements. The cases are evaluated as:

if($totaltime == ($totaltime < 1)) {
  echo "That was fast!";
  break;
}
if($totaltime == ($totaltime > 1)) {
  echo "Not fast!";
  break;
}
...

Clearly 0 == false for 2nd IF is true and hence the result.

Thanks, Vikas.

Comments

0

Others have mentioned why this is occurring (misuse of a conditional in the case statement), but they haven't offered alternatives. Switch is meant to cover specific arguments like { 0, 1, 2, 3..100, 101 } etc. It separates out specific arguments or ranges rather than performing a simple if/else (as you've used it). You can rewrite your arguments to pull it off though:

switch ($totaltime) {

    case (0):
        echo "That was fast!";
        break;

    case (1..PHP_INT_MAX):
        echo "Not fast!";
        break;

    default:
        echo "That's slooooow";
        break;
}

Here the .. allows a range to be covered, so anything from 1 to integer max is covered by that case. The 0 is handled explicitly and all others (re: < 0) are covered by the default case.

3 Comments

+1, Thanku for your response. This is what i am looking for. when $totaltime = 10; it results in "That's slooooow"; instead of "Not fast!";
-1 PHP doesn't support ranges like you used in a switch/case. Your case (1..PHP_INT_MAX): will actually return the concatenated value of 1 and PHP_INT_MAX (12147483647). I guess you did too much Pascal lately and are mixing PHP and Pascal syntax :p.
@wimvds: Thanks for the comment and the info. I guess I've been spending too much time in other languages lately.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.