having the integer 0 as switch parameter will take the first result "foo":
$data=0; // $data is usually coming from somewhere else, set to 0 here to show the problem
switch ($data) :
case "anything":
echo "foo";
break;
case 0:
echo "zero";
break;
default:
echo "bar";
endswitch;
How do I change this, so the switch will write "zero" as expected?
The switch/case statement uses loose comparison, and, like it or not, 0 == "anything" is true:
Comparison Operators
[...] If you compare a number with a string or the comparison involves
numerical strings, then each string is converted to a number and the
comparison performed numerically. These rules also apply to the switch
statement. [...]
var_dump(0 == "a"); // 0 == 0 -> true
One solution is to change all case statements to string, and do a string comparison:
$data = 0;
switch ((string) $data): ## <- changed this
case "anything":
echo "foo";
break;
case "0": ## <- and this
echo "zero";
break;
default:
echo "bar";
endswitch;
Switch/case statement uses "loose-comparison" (i.e. ==. in this case, 0 also means false and 1 also means true. (http://www.php.net/manual/en/types.comparisons.php#types.comparisions-loose)
To avoid this problem, two solutions:
1) As suggested by #zzlalani, add quotes.
case '0': ...
2) Explicitly cast the switch statement to force a strict comparison (===)
switch((string)($data)) { ... }
Do like this
$data=0;
switch ($data)
{
case 0:
echo "bar";
break;
default:
echo "foo";
break;
}
EDIT :
How do I change this, so the switch will write "zero" as expected?
You need to move your case statement above.
$data=0;
switch ($data) :
case 0: // Moved this case to the begining
echo "zero";
break;
case "anything":
echo "foo";
break;
default:
echo "bar";
endswitch;
This is because switch does not do a "strict-type" checking.
Related
Can someone please explain why the case "a" is never reached in below code and why it will always execute case 0
switch ("a") {
case 0:
echo "0";
break;
case "a": // never reached because "a" is already matched with 0
echo "a";
break;
}
PHP, like JavaScript or Perl, is a loosely-typed language and will attempt to guess what you want to do. In this case, it changed your string to the closest integer it could find, which is zero. In other words, "a" == 0 is a true statement in PHP.
More on this topic can be found in the PHP documentation. I suggest you typecast the value in the switch statement, or replace it with an if/elseif/else construct.
As of PHP 8.0, this behaviour has changed and now the integer value will always be changed to a string before comparison between the two types. Strictly typing and comparing your variables remains the recommended practice, however.
You can not used mix-cases in a switch statement as PHP will interpret the meaning of what you mean.
In layman's terms, it will try to find the 'value of "a"' which is not defined to the processor, and hence is 0 in this case.
Same will go for the code below:
<?php
$x = "a";
switch($x)
{
case "c":
echo "c";
break;
case 1:
echo "1";
break;
case 0:
echo "0";
break;
case "a":
echo "a";
break;
case false:
echo "false";
break;
default:
echo "def";
break;
}
?>
Documentation is available at PHP.net
The reason for this is because switch uses a loose comparison ==
That said:
if ("a" == 0) // TRUE
if ("a" == true) // TRUE
Pretty much anything else will evaluate to false. (except "a" == "a")
So, if you have the need to compare against both strings and integers, you should just convert to string for the comparison.
//$var = "a";
$var = 0;
$var = strval($var);
switch ($var) {
case '0':
echo "0";
break;
case 'a':
echo "a";
break;
}
The variable type used on case() should be same type used in switch().
<?php
switch ("a") {
case "0":
echo "0";
break;
case "a": // never reached because "a" is already matched with 0
echo "a";
break;
}
For integer type:
<?php
switch (1) {
case 0:
echo 0;
break;
case 1: // never reached because "a" is already matched with 0
echo 1;
break;
}
This question already has answers here:
How to handle a PHP switch with different types?
(5 answers)
Closed 9 years ago.
The following switch case statement was supposed to execute the value of case "january": but instead it is executing the value of case 0: ,can anybody tell me why it is doing this?
CODE:
<?php
$a = "january";
switch ($a)
{
case 0:
case 3:
echo "The value is either 0 or 3";
break;
echo "0/2";
break;
case "january":
echo "january";
break;
case "march":
echo "The value is ";
break;
case 2:
echo "The value is 2";
break;
default:
echo "Here is ur default message";
break;
}
?>
By the way it is doing the same for the case "march"....?
$a = 'january';
var_dump($a == 0);
var_dump($a === 0);
var_dump($a == '0');
var_dump($a === '0');
Output:
bool(true)
bool(false)
bool(false)
bool(false)
Read up on Type Juggling. Apparently switch uses loose comparison:
Note:
Note that switch/case does loose comparision.
PHP has some problems that can cause this kind of behaviour, in this case the problem comes from the fact that you are using different types on your Switch.
Try this code:
echo (0 == "january") ? "true\n" : "false\n"; // Echoes true
One way to work around this is to use only strings on your switch, like so:
switch ($a)
{
case "0":
case "3":
echo "The value is either 0 or 3";
break;
echo "0/2";
break;
case "january":
echo "january";
break;
case "march":
echo "The value is ";
break;
case "2":
echo "The value is 2";
break;
default:
echo "Here is ur default message";
break;
}
This will work fine, because 0 == "0" but "january" != "0"
Switch uses simple == to compare the values of the variable with the ones on each case.
You need to put quotes around the numbers. You can't mix numbers and strings when using a switch statement.
switch(false) {
case 'blogHitd':
echo('ddd');
break;
case false:
echo('bbbb');
break;
default:
echo 'alert("error action");';
}
-------output------
bbbb
switch(true) {
case 'blogHitd':
echo('ddd');
break;
case true:
echo('bbbb');
break;
default:
echo 'alert("error action");';
}
-------a strange output-------
ddd
Why, when I pass the value of true it will always select the first one?
From the PHP documentation on Booleans:
When converting to boolean, the following values are considered FALSE:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the string "0"
an array with zero
elements
an object with zero member variables (PHP 4 only)
the special
type NULL (including unset variables
SimpleXML objects created from
empty tags
Every other value is considered TRUE (including any resource).
The last sentence of this quoted passage is the line of interest in your case.
Switching "true" is only useful if you've got functions or variables in your "case" line
switch(true)
{
case is_array($array):
echo 'array';
break;
default:
echo 'something else';
break;
}
Note that switch/case does loose comparision.
http://www.php.net/manual/en/types.comparisons.php#types.comparisions-loose
PHP will typecast values for you, don't forget:
php > var_dump(true == 'bloghitd');
bool(true)
In this scenario the switch only runs the first valid case.
It is useful in the case that you have more than one possible answer but you want to run only the first one. For example:
switch(true){
case 1 == 2:
echo '1 == 2';
break;
case 2 == 2:
echo '2 == 2';
break;
case 3 == 3:
echo '3 == 3';
break;
case 4 == 1:
echo '4 == 1';
break;
}
The output:
2 == 2
Both the second and third cases are true, but we only get the second (which is the first TRUE).
I have this code where $difference=0
switch ($difference)
{
case 0<=$difference && $difference<300:
return "A";
break;
case 300<=$difference && $difference<600:
return "B";
break;
}
I think that switch must return A but it returs B. Whats wrong ???
I'm posting this merely as informative.
Switches can be used with expressions, however this is tricky to do:
<?php
$value = 300;
$other = 1;
switch (true) {
case $value <= 300 && $other:
$var = 'A';
break;
case $value >= 300 && !$other:
$var = 'B';
break;
case $value >= 300 && $other:
$var = 'C';
break;
case $value > 300 && $other:
$var = 'D';
break;
default:
$var = 'FALSE';
break;
}
echo $var;
The above code will display 'C' correctly. A combination of if/else statements is equivalent but I tend to find the switch more readable. Be sure to always include a default case whose value you can rely on (or maybe return from the function, throw an exception, etc).
You can also compare other variables, types, call functions (although not recommended), etc to match the value declared in the switch statement (in this case, true but can be an integer, string or any other base type).
Switches with expressions like you are using will not be evaluated as you might think. Use an if statement instead:
if(0<=$difference && $difference<300)
{
return "A";
}
else if(300<=$difference && $difference<600)
{
return "B";
}
In this case what is happening is $difference being equal to 0 is being interpreted as false. Thus you have switch(false). Each case is evaluated as a whole and there for case 2 actually returns false thus matching the switch statements evaluation and returning B. It also has to do with loose type checking. PHP.net
I was hoping someone had a clue as to why I got the following outputs because I was expecting something else.
$x = NULL;
switch ($x) {
case "0":
echo "String";
break;
case 0:
echo "Integer";
break;
case NULL:
echo "NULL";
break;
case FALSE:
echo "Boolean";
break;
case "":
echo "Empty string";
break;
default:
echo "Something else";
break;
}
// outputs "Integer" was expecting "NULL"
$x=6;
switch ($x) {
case "6b":
echo "6b";
break;
case "6":
echo "6 empty";
break;
case 6:
echo "6 full";
break;
default:
echo "6 half";
break;
}
// outputs "6b" was expecting "6 empty"
The manual says:
Note that switch/case does loose comparision.
It will first check whether NULL == "0" which is false as NULL as a string is not "0".
NULL as integer is 0 so that will match - printing Integer.
For the 6, it will convert the cases to integers - "6b" will become 6 which is equal.
So it's because:
NULL != "0";
NULL == 0;
"6b" == 6;
Note:
Note that switch/case does loose comparision.
http://php.net/manual/en/control-structures.switch.php
So in stead of doing a comparison like: $x === 0 you do $x == 0
The comparison done by switch/case works with type jugling.
Basically, it uses the == operator, and not the === one.
Quoting Comparison Operators :
If you compare a number with a string or the comparison involves
numerical strings, then each string is converted to a number and the
comparison performed numerically. These rules also apply to the switch
statement.
$x is automatically converted to an integer when doing the comparison "$x = 0". You might want to use an if/else if structure instead, and use $x === 0 to do the comparison. === means "strictly equal to".