Jagdeep Singh
Jagdeep Singh

Reputation: 885

php switch statement error on int = 0

I am having a problem in php switch case.

When i set $number=0 it should run very first case but here this code returns 10-20K that is in second case.

I checked comparison operators, tested them in if else case they return correct values but here first case do not run on $number=0

Why is this happening ? php consider 0 as false or something wrong in code ?

Link to codepad paste http://codepad.org/2glDh39K

also here is the code

<?php

$number = 0;

    switch ($number) {
     case ($number <= 10000):
            echo "0-10K";
           break;
        case ($number > 10000 && $number <= 20000):
            echo "10-20K";
            break;
        case ($number > 20000 && $number <= 30000):
            echo "20-30K";
            break;
        case ($number > 30000 && $number <= 40000):
            echo "30-40K";
            break;
        case ($number > 40000 && $number <= 50000):
            echo "40-50K";
            break;
        case ($number > 50000 && $number <= 60000):
            echo "50-60K";
            break;
        case ($number > 60000 && $number <= 70000):
            echo "60-70K";
            break;
        case ($number > 70000 && $number <= 80000):
            echo "70-80K";
            break;
        case ($number > 80000 && $number <= 90000):
            echo "80-90K";
            break;
        case ($number > 90000):
            echo "90K+";
            break;

        default: //default
            echo "N/A";
            break;
}

?>

Upvotes: 4

Views: 3353

Answers (7)

xdazz
xdazz

Reputation: 160863

switch ($number) {
 case ($number <= 10000):   // check $number == ($number <= 10000)
       echo "0-10K";
       break;
 // you hit the below because `0 == false` is true in php
 case ($number > 10000 && $number <= 20000): // check $number == ($number > 10000 && $number <= 20000)
        echo "10-20K";
        break;
 // ...

But you could do it with less code:

function showRange($number) {
    if ($number > 90000) {
       echo "90K+";
       return;
    }
    echo sprintf("%s-%sK", (int) ($number / 10000) * 10, ((int) ($number / 10000) +1) * 10 );
}

Upvotes: 4

Jon
Jon

Reputation: 437424

You are almost using the switch in reverse, but not quite. You need to either go fully into reverse by writing switch(true):

switch (true) { // IMPORTANT CHANGE HERE!
    case ($number <= 10000):
        echo "0-10K";
       break;
    case ($number > 10000 && $number <= 20000):
        echo "10-20K";
        break;
    // etc
}

or otherwise change the whole thing to if/else:

if ($number <= 10000) {
    echo "0-10K";
else if ($number > 10000 && $number <= 20000) {
    echo "10-20K";
}
// etc

Two important notes:

  1. Reverse switch usually looks terribly counter-intuitive the first time you see it. Please do not use it if you don't feel comfortable with it.
  2. Your conditionals could be simplified -- assuming they appear in order, each $number > X part is made redundant by the fact that the check in the previous conditional ($number <= X) has already failed. However, it can be argued that keeping the checks makes the code more robust in the face of modification.

Upvotes: 7

Whisperity
Whisperity

Reputation: 3042

$number = 0;
var_dump($number); // int(0)

If you modify the statement to be case ($number > 0 && $number <= 10000):, it strangely works. But it works with any arbitrary lookup ($number > 9091 && $number <= 10000) entered.

Even with the complete bollock below:

$number = 0;
$jonskeet = false;

switch ($number)
{
    case ($jonskeet === true && $number <= 10000):
        echo "0-10K";
        // ...

It will output 0-10K even though the same condition in an if statement won't work.

The problem is that select is not to be used with long conditionals. select can be used to do something if the value of a variable is equal to what is after the case keyword. See:

select ($user_rank)
{
    case 0:
        return "guest";
        break;
    case 1:
        return "user";
        break;
    // ...
    default:
        return "unknown";
        break;
}

But you have long conditions in the cases of your code.

case ($number <= 10000):
    echo "0-10K";
    break;
case ($number > 10000 && $number <= 20000):
    echo "10-20K";
    break;

Running this first translates $number <= 10000 to TRUE and $number > 10000 && $number <= 20000 to FALSE, like two statements. And after this, your code is executed in the manner below:

case TRUE:
    echo "0-10K";
    break;
case FALSE:
    echo "10-20K";
    break;

$number is 0, but it can evaulate to FALSE too, this is why you get the not desired output.

As a solution, you should translate your code to have an if-elseif-else setup:

 if ( $number < 10000 ) {
     echo "0-10K";
 } else if ( $number > 10000 && $number <= 20000 ) {
     echo "10-20K";
 // ...
 } else {
     echo "N/A";
 }

Upvotes: 3

Database_Query
Database_Query

Reputation: 634

Here, if $i is equal to 0, PHP would execute all of the echo statements!

so its execute the statement of next case and in that case there is break so out from it

so use the if-else-if instead of switch case

if ($number <= 10000){
  echo "0-10K";
}elseif(  $number <= 20000){
  echo "10-20K";
}elseif(  $number <= 30000){
  echo "20-30K";
}elseif(  $number <= 40000){
  echo "90K+";
}

 ...

elseif(  $number <= 90000)
     echo "80-90K";

}elseif($number > 90000){
echo "90K+";
}

Upvotes: 1

Soojoo
Soojoo

Reputation: 2156

You can't really do switch case for a range of number.Use if(){} else{} for this purpose.

Upvotes: 0

null
null

Reputation: 11869

Yes, for PHP 0 is FALSE (unless you use ===). And yes, your code is incorrect - switch isn't for comparing ranges - it's for comparing values (at least in PHP, in Ruby or Perl 6 it's another matter), like there.

switch ($letter) {
case 'a':
    echo "A?";
    break;
default:
    echo "Unknown letter";
    break;
}

In your case, you compare number to conditions - those either return true or false. As 0 is false, the second condition catches. switch wasn't made for code like that, I would use if else instead or rewrite your logic - repeating isn't good idea.

$range_number = floor($number / 1000);
echo $range_number, $range_number ? "K" : "", "-", $range_number + 1, "K";

(by the way, I know that switch (true) works, but don't use it - it's ugly hack)

Upvotes: 1

Lix
Lix

Reputation: 47976

When you execute a switch case method, you can't match against a boolean value like that. You need only compare the resulting value.

I think you should rewrite your code to use if...then...elseif statements.

if ($number <= 10000){
  echo "0-10K";
}elseif($number <= 20000){
  echo "10-20K";
}elseif($number <= 30000){
  echo "20-30K";
}elseif($number <= 40000){
  ...
}

By using this method you don't need to make two checks each time because the previous if statements check those conditions as well. IE: If you reach the second if statement, you already know that the value is not smaller than (or equal to) 1000 therefore it must be larger than 10000.

Upvotes: 3

Related Questions