php Switch statement and 0 - php

Hi i see a code today like that
$i=0;
switch($i){
case 'TEST': print "Test";break;
case 0: print "0";break;
}
The normal output seems to be 0 but it prints Test. Then i try to understand it and got a solution here. That is, when compare a number with string then string will convert to number and comparison performed numerically. OK then its ok to get the output Test.
But what if i set identical to it like
$i=0;
switch($i){
case ($a === 'Test'): print "Text";break;
case ($a === 0): print "0";break;
}
That also give the result Test so i am confused here. And if i use == instead of === then it show blank. So please clear me that.

Do you have to make $i as numeric?
Let it be string too...
$i="0";
switch($i){
case 'Test': print "Text";break;
case '0': print "0";break;
}
That prints 0...

Switch treats 0 as false so here you can go:
$i=0;
switch(true){
case $i === 'TEST': print "Test";
break;
case $i === 0 : print "0";
break;
}

Related

Please explain why PHP switch case is always executing case 0 in this code

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;
}

PHP switch($p) take the first case if $p == 1

I have this code:
$r = do_something($data);
if ($r == 1)
{
echo "it is 1";
}
switch ($r)
{
case "a":
print "a";
break;
case "b":
print "b";
break;
default:
print "default";
}
With this code the output should be:
it is 1
default
but the surprise is that the output is:
it is 1
a
How is this possible?
edit: after some test i see that:
$r === true.
so the new question is: when the var is true how work the switch?
PHP's "type juggling" rules are rather tricky, and occasionally unintuitive and even controversial. There's a great big table in the manual showing what happens when you make comparisons of various sorts, but to explain your particular case:
You are working with three different types: $r is currently true, which is a boolean; the if statement tests against 1, which is an integer; and the switch statement tests against "a" and "b", which are strings.
When you compare a boolean to an integer, PHP first converts the integer to a boolean, using the rule that 0 converts to false, and anything else converts to true. This has the effect in your case of $r == 1 evaluating to true, but $r == 42 would also evaluate to true.
When you compare a boolean to a string, a similar thing happens, but here the string gets converted according to this rule: an empty string is false, anything else is true. So $r == "a" also evaluates to true in your example, which is why that branch of the switch statement is executed.
To get the result you were hoping for, you need to force the type conversion to happen in a different way. There are a few ways to do this, but the simplest in your case is to cast $r to the same type as what you're comparing it against:
(int)$r will give you the integer 1 for a value of true, and 0 for false, so if ( (int)$r == 1 ) will give the same result, but be clearer that $r wasn't actually an integer at that point in the code.
more importantly, (string)$r will give you the string "1", so switch( (string)$r ) won't have to do any "type juggling" to compare against strings like "a" and "b", and you won't get any surprises there.
I think your do_something($data) function returns 1 if it does what it suppose to do. I tried this code and it works. Here it is.
function do_something($data){
return 1;
}
$r= do_something('abc');
if ($r == 1)
{
echo "it is 1<br />";
}
switch ($r)
{
case "a" : print "a"; break;
case "b" : print "b"; break;
default : print "default";
}
OUTPUT:
it is 1
default

How to use switch with integer 0 in PHP?

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.

PHP switch and case logical control

It possible to have logical control on case ?
ie:
$v = 0;
$s = 1;
switch($v)
{
case $s < $v:
// Do some operation
break;
case $s > $v:
// Do some other operation
break;
}
Is there a way to do something similar ?
The condition that is passed to switch is a value the cases are compared against. The condition (in your question $v) is evaluated once and then PHP seeks for the first case that matches the result.
From the manual (after Example #2), emphasis added:
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.
In your question switch ($v) is same as if you'd written: switch (0), because $v = 0. Then, your switch will try to find a case which equals to 0. And, just as #Kris said:
$s < $v evaluates to false, which triggers on the $v because it is 0 in here.
If you have to use conditions in case statements, your switch-condition should be a boolean, e.g.:
$v = 0;
$s = 1;
switch (true) {
case ($s < $v):
echo 's is smaller than v';
break;
case ($s > $v):
echo 's is bigger than v';
break;
}
Now your switch tries to seek the first case that evaluates to true, which in this case would be $s > $v.
Note that while the switch-condition is evaluated only once, cases are each evaluated in order:
$a = 1;
switch ($a) {
case 2:
echo 'two';
break;
case (++$a > 2):
break;
default:
echo $a;
}
echoes '2' from default-case, because when comparing $a to "2" $a was 1 and the case is discarded; while:
$a = 1;
switch ($a) {
case (++$a > 2):
break;
case 2:
echo 'two';
break;
default:
echo $a;
}
echoes 'two' from case '2' because ++$a > 2 increases $a but doesn't match $a.
default is a fallback and its position doesn't matter.
NB: the aforementioned switches are fugly and esoteric and are only provided as a proof-of-example.
Not the most readable use of, but yes you can.
Use if/else - if/elseif/else structure if you do need just a simple comparison.
This will not work, every case needs to be a scalar value. in your example case it is even worse, it may seem to work but...
$s < $v evaluates to false, which triggers on the $v because it is 0 in here.
http://php.net/manual/en/control-structures.elseif.php
if ($a > $b) {
echo "a is bigger than b";
} elseif ($a == $b) {
echo "a is equal to b";
} else {
echo "a is smaller than b";
}

question regarding switch conditionals in php

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".

Categories