switch loop doesnt recognize zero "0" php - php

I have this simple function to convert the number of comments of an user to types of members.
function checkMemberN($numMessages){
$n= $numMessages;
switch ($n) {
case ($n<50): $type="New"; break;
case ($n>=50 && $n<250):$type="Frequent";break;
case ($n>=250 && $n<1000): $type="Master";break;
default: $type="undefinded";
}
return $type;
}
echo checkMemberN(0);
It looks like it doesn't recognize zero (0), because when I put 1 or a higher number it retrieves the correct user type. What am I doing wrong?

When you use switch, the first case which returns a value equal to the given one is selected. In this case, your argument (zero) is a false-y value. That's why the first case that returns false is chosen: "Frequent".
To fix it, you can do this:
if ($n<50) {
$type = "New";
} else if ($n>=50 && $n<250) {
$type = "Frequent";
} else if ($n>=250 && $n<1000) {
$type = "Master";
} else {
$type = "undefined";
}
If you still want to use switch, you can change the argument to true:
switch (true) {
case ($n<50): $type="New"; break;
case ($n>=50 && $n<250):$type="Frequent";break;
case ($n>=250 && $n<1000): $type="Master";break;
default: $type="undefinded";
}
Here, the first case which returns true will be used.

Related

Change if condition dynamically

I'd like to dynamically change a condition, depending on whether or not a table is empty.
If the table is empty, it should record all data up to yesterday, if not empty, it should record today's data.
My current code is not working:
$db->get('history');
$emptyTable = $db->count; // This return 0 or 1
$condition = setCondition($emptyTable);
foreach($extract as $trade) {
$date = strtotime($trade['Date']);
$today = strtotime(date("d/m/Y"));
if($condition) {
// do something
}
}
function setCondition($bool) {
switch ($bool) {
case 1:
return $date == $today;
break;
case 0:
return $date < $today;
break;
}
}
You are not passing $date and $today to your function and call it inside foreach and enclose the return part in setCondition so that it will return the string ..
foreach($extract as $trade) {
$date = strtotime($trade['Date']);
$today = strtotime(date("d/m/Y"));
$condition = setCondition($emptyTable,$today,$date);
// echo $condition//condition string
if($condition) {
// do something
}
}
function setCondition($bool,$today,$date) {
switch ($bool) {
case 1:
return "'$date' == '$today'";
break;
case 0:
return "'$date' < '$today'";
break;
}
}
DEMO
Your condition itself needs to be a call to a function returning a boolean value. This is what your setCondition function does:
function setCondition($bool) {
switch ($bool) {
case 1:
return $date == $today;
break;
case 0:
return $date < $today;
break;
}
}
Since it does not set anything, I suggest you rename it evaluateCondition.
Henceforth, you can directly call this function as a condition:
if(evaluateCondition($booleanVariableToTest)) {
// do something
}
Regarding why your code does not work: you basically evaluate $condition once, at the beginning:
$condition = setCondition($emptyTable);
After that, $condition never changes. Therefore, it is not dynamically re-evaluated.
Edit
From reading a comment of you, I understand that you're not actually trying to dynamically evaluate a condition, but statically evaluate it, depending on other parameters (namely, $date and $today).
Your function needs to take these variables as arguments, so their names actually mean something in the scope of this function. The right code is:
function setCondition($bool, $date, $today) {
switch ($bool) {
case 1:
return $date == $today;
break;
case 0:
return $date < $today;
break;
}
}
In this case, you do not need to call the setCondition function at every iteration, so your if test remains:
if($condition) {
// do something
}

Can I use a strpos in a switch case?

Consider:
I have a variable called $field that from time to time may have, among others, values such as action, id, and another_term. I want to use a switch structure to sift the values:
switch ($field) {
case 'action':
// do something
break;
case 'id':
// do something
break;
case (strpos($field, '_term')):
// do something else
break;
}
The first two cases work. The third does not. I am thinking that this is an incorrect use of a switch statement. Is this better handled as an if/else sequence?
You can do it using the switch statement like this:
$field = 'bla bla_term bla';
switch (true) {
case $field === 'action':
echo 'action';
break;
case $field === 'id':
echo 'id';
break;
case strpos($field, '_term') >= 0:
echo '_term';
break;
}
The switch statement just compares the expressions in each case block to the value in the switch parentheses.
Expressions are units of code that you can reduce to a value, such as 2 + 3 or strpos(...). In PHP most things are expressions.
Here is an annotated version of the above example:
// We are going to compare each case against
// the 'true' value
switch (true) {
// This expression returns true if $field
// equals 'action'
case $field === 'action':
echo 'action';
break;
// This expression returns true if $field
// equals 'id'
case $field === 'id':
echo 'id';
break;
// This expression returns true if the
// return value of strpos is >= 0
case strpos($field, '_term') >= 0:
echo '_term';
break;
}
If you want to use the return value of the strpos call then you can just assign it (assignments are expressions in PHP):
case ($pos = strpos($field, '_term')) >= 0:
echo '_term at position ' . $pos;
break;
switch is just a sort of if x == y with y being any of the matching cases.
case (strpos($field, '_term')) would result in a -1 if match is not found or the point where "_term" was found (0 through string length -1 ) and not the field name.
If you're looking to catch anything with there phrase "_term" in the field do
$matches = array();
if(preg_match('/(.+)_term$/', $field, $matches)) {
$field = $matches[1];
}
this will replace the field value "address_term" or what ever "something_term" to just "address" or "something"

Switch statement using strstr always validates as true?

I have the following switch statement.
The URL contains a referral ID e.g twitter, facebook or an email e.g mail#mail.com. This is stored as $ref
I have the following switch statement:
switch ($ref) {
case "twitter":
echo "twitter";
break;
case "facebook":
echo "facbeook";
break;
case "blog":
echo "blog";
break;
case strstr($ref,'#'):
echo "email = ".$ref;
default:
echo "no referral found";
break;
}
However if URL is passed with nothing (e.g just www.mything.co.uk) then I wish to go to the default case.
Instead, I get the following output:
email = no referral found
Why does the default also include the text I set for case strstr($ref,'#') ?
OP question: "Why does the default also include the text I set for case strstr($ref,'#') ?"
Answer: there's no break; following the output, and thus falls through to the default case.
UPDATE: Addressing the issue of putting a statement within a case, I'm also including an easy work-around:
switch ($ref) {
case "twitter":
echo "twitter";
break;
case "facebook":
echo "facbeook";
break;
case "blog":
echo "blog";
break;
default:
if (strstr($ref,'#')) {
echo "email = ".$ref;
} else {
echo "no referral found";
}
break;
}
When $ref is an empty String, then strstr($ref,'#'); returns an empty string too, this is why the case strstr($ref,'#'): matches the switch input $ref.
The problem is, you can't even use a email validation function like
filter_var($ref, FILTER_VALIDATE_EMAIL)
That would return false in case of an empty input instead of an empty string, but switch does loose comparison, meaning that an "" == false would return true:
http://php.net/manual/en/types.comparisons.php#types.comparisions-loose
Thus the only solution I see is to use an if statement using the === operator:
if($ref == 'twitter') {
echo "twitter";
} else if($ref == 'facebook') {
echo "facbeook";
} else if($ref == 'blog') {
echo "blog";
} else if($ref === filter_var($ref, FILTER_VALIDATE_EMAIL)) {
echo "email = ".$ref;
} else {
echo "no referral found";
}
That's because your test is performed like if ($ref == strstr($ref, '#')), where strstr returns false which equals an empty string. You cannot really use dynamic comparisons in switch statements. Use if..else if you need that. Alternatively, abuse switch a bit:
switch (true) {
case $ref == 'twitter':
..
case strstr($ref, '#'):
..
}
That will work:
case (strstr($ref, '#') ? true : false):
But it's not really good of practice.

php switch for a null string

For the following php program with a switch statement, why '' give me $vSS=2 instead of =1?
Quite strange to me. I am using PHP 5.5.9.
I can add case '': to resolve the problem, but I am curious why PHP give $vSS=2 instead of
$vSS=1. Is it normal or a bug?
<?php
R(15); // 1 ok
R(''); // why give me 2
R(40); // 2 ok
R(70); // 3 ok
#
function R($SS){
switch($SS){
case $SS<=20: $vSS=1;break;
case ($SS>20 and $SS<=49.9): $vSS=2; // why here?
if($SS == '') echo "DEBUG: SS is a null string.<br>\n";
break;
case ($SS<=100 and $SS>49.9): $vSS=3; break;
default:$vSS=0 ;
}
echo "DEBUG:(SS/vSS) $SS:$vSS\n";
}
?>
------ RESULT
DEBUG:(SS/vSS) 15:1
DEBUG: SS is a null string.<br>
DEBUG:(SS/vSS) :2
DEBUG:(SS/vSS) 40:2
DEBUG:(SS/vSS) 70:3
You don't understand how switch works. It compares the value in switch($SS) with each of the case values, it doesn't just test each case. So
switch ($SS) {
case $SS<=20:
is similar to:
if ($SS == ($SS<=20))
The reason the second case is being executed is because ($SS > 20 && $SS <= 49.9) is false, and false is considered equal to zero or an empty string.
You shouldn't use switch for what you're doing, you should use if/then/elseif/else:
if ($SS <= 20) {
$vSS = 1;
} elseif ($SS <= 49.9) {
$vSS = 2;
} else {
$vSS = 0;
}
#Barmar is right, expression in case() is compared to switch(something_here) but you don't have to cahnge your all your code to if/elsif/elsif/.../... logic. Just change switch() statement to true
switch(true) { // <-- this part only
case $SS<=20:
$vSS=1;
break;
case ($SS>20 and $SS<=49.9):
$vSS=2; // why here?
// must not be here
// if($SS == '') echo "DEBUG: SS is a null string.<br>\n";
break;
case ($SS<=100 and $SS>49.9):
$vSS=3;
break;
case $SS=='': // you can check it here
echo "DEBUG: SS is a null string.<br>\n";
break;
default:
$vSS=0 ;
}

Comparisons in switch cases, are they valid?

Thats the code:
switch (true)
{
case (isset($_REQUEST['a']) && is_numeric($_REQUEST['a']) && ($_REQUEST['a'] > 0)):
case (isset($_REQUEST['b']) && is_string($_REQUEST['b']) && in_array($_REQUEST['b'], $barray)):
case (isset($_REQUEST['c']) && is_numeric($_REQUEST['c']) && ($_REQUEST['c'] > 0) && ($_REQUEST['c'] <= $cbase)):
try { echo "Foo"; }
catch(Exception $e) { echo $e->getMessage(); }
break;
default:
echo "Bar"; break;
}
I'm wondering if these are allowed for use in switch cases?
Very soon I must use switch because of many comparisons and willing to try it. In this case 3rd case gives me always correct output, even when $_REQUEST['c'] is bigger than $cbase, while should fall to default :|
Yes this is valid. Using switch(TRUE) enables you to have strict comparisons in a switch statement. check this examples:
Not typesafe:
$a = '1';
switch($a) {
case 1 :
// do something (will get executed)
break;
case '1' :
// do something:
break;
}
Better:
$a = '1';
switch(TRUE) {
case $a === 1 :
// do something; (will not get executed)
break;
case $a === '1' :
// .. do something;
break;
}
Also this usage allows for more complex case statements, like this:
switch(TRUE) {
case strpos($input, 'a') === 0 :
// do something
break;
case strpos($input, 'b') === 0 :
// do something
break;
}

Categories