Can I use a strpos in a switch case? - php

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"

Related

switch loop doesnt recognize zero "0" 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.

Is there a more elegant way to execute this switch statement?

I have a large switch statement in my code, and I want it to do something like this:
// assign $foo
switch ($foo) {
case 1:
case 2:
// do X, then break if 1, do Y and break if 2
case 3:
case 4:
case 5:
// do A & B, break if 3, do C if 4 or 5, do D if 5 and then break
}
Such "groups" are prevalent throughout the switch statement and currently I just repeat the logic, keeping each case separate.
Am I wrong in assuming that this could be restructured into something that's objectively "better"?
Edit: I excluded my original code snippet from the question, since it had deeply flawed logic and didn't conform to the basic concepts of using a switch, replacing it with pseudocode that resembles the desired result.
As commented, that switch doesn't actually work as you think.
You're simply looking for:
if (in_array($foo, [1, 2])) {
...
if ($foo == 2) {
...
}
}
Alternatively:
switch ($foo) {
case 1:
case 2:
...
if ($foo == 2) {
...
}
break;
}
TLDR;
For simple "is it this", use a switch, if you need logical checks, use an if
The answer;
What you are asking is quite subjective, while using a switch for something simple is good, i.e;
<?php
$case = getCaseFrom("X"); // Let's say this = "a"
switch ($case)
{
case "a" : {
$thing = "a";
break;
}
case "b" : {
$thing = "b";
break;
}
case "c" : {
$thing = "c";
break;
}
default : {
$thing = "d";
}
}
?>
The same could be achieved by using;
<?php
$case = getCaseFrom("x");
$thing = $case;
// And even shorter;
$thing = getCaseFrom("x");
?>
Whereas, if you needed some logic to this...
<?php
$operator = getOperatorFrom("X"); // In this case, add
$num1 = 10;
$num2 = 2;
switch ($operator)
{
case "add" : {
$res = num1 + num2;
break;
}
case "subtract" : {
$res = num1 - num2;
break;
}
case "multiply" : {
$res = num1 * num2;
break;
}
case "divide" : {
$res = num1 / num2;
break;
}
}
?>
The alternative;
And of course, all of the above switches case be done using if else clauses, but a switch (IMO) is a neater, and more readable approach depending on what your certain criteria are (see the drawbacks).
The easiest way to look at it is;
If you need to check if something matches a value, use an if, if it is an enumerated set of values (let's say 1 to 4), a switch is subjectively better
The drawbacks;
A switch also doesn't let you have multiple "and" checks in the same statement, for example;
<?php
$case = getCaseFrom("X"); // In this case, a (does not have "b")
switch ($case)
{
case "a" :
case "b" : {
// This checks for a or b, not both, despite this not containing "b"
// this will still be accessed
break;
}
case "c" : {
// This will not be used as the break stops
// it from falling through to this clause
break;
}
}
if (stristr("a", $case) && stristr("b", $case))
{
// This checks to see if case contains a AND b
// therefore, this will not be used, as this
// does not have both a and b in $case
}
else if (stristr("a", $case) || stristr("b", $case))
{
// This checks to see if case contains a OR b
// therefore, this will be used, as this
// is checking that $case has "a" or "b" in it
// This is the same as the switch in this instance as it uses "or"
}
The noteworthy;
To be aware of the following also would be useful;
Inside a switches case, you cannot use login, for example;
case getThing("a") :
would cause an error
NB: Of course, when using the case statements, you don't need the curly braces added, they are mainly for code folding and ease of reading

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

php use switch within echo statement

I need to use a statement like switch within echo statement
I found a way for this ,but i think this is not the best way for this
when we want to use IF inside echo,write some thing like:
echo ((condition)?'print this if condition is True':'print this if condition is False');
we could use this method for a way like switch:
echo ((case1)?'case 1 result':((case2)?'case2 result':((case3)?'case3 result':'default result')));
are you know a better way for this?
Your example is called ternary operators its basically short hand for an if statement.
So in your second example you're just doing a load of chained if then else's
You're far better off doing something like this
switch ($type)) {
case "txt":
$output = "images/doctypes/icon_txt.gif";
break;
case "doc":
$output = "images/doctypes/icon_doc.gif";
break;
case "docx":
$output = "images/doctypes/icon_doc.gif";
break;
case "pdf":
$output = "images/doctypes/icon_pdf.gif";
break;
case "xls":
$output = "images/doctypes/icon_xls.gif";
break;
case "xlsx":
$output = "images/doctypes/icon_xls.gif";
break;
case "ppt":
$output = "images/doctypes/icon_ppt.gif";
break;
case "pptx":
$output = "images/doctypes/icon_txt.gif";
break;
case "rtf":
$output = "images/doctypes/icon_txt.gif";
break;
case "zip":
$output = "images/doctypes/icon_zip.gif";
break;
case "rar":
$output = "images/doctypes/icon_zip.gif";
break;
case "mdb":
$output = "images/doctypes/mdb.gif";
break;
default:
$output = "images/doctypes/icon_generic.gif";
};
echo $output;
Hmm. If I understand correctly, you want to know the how-maniest condition was the first successful one?
I just thought this up... See if it fits you.
Just replace the false/true with your conditions.
$i = 0;
++$i AND false OR // 1
++$i AND false OR // 2
++$i AND false OR // 3
++$i AND true OR // 4 (here we go)
++$i AND false OR // 5
++$i AND true OR // 6 (ignored)
++$i AND false OR // 7
$i = 0; // 0
echo "case" . $i . " result"; // echoes 'case4 result'
EDIT:
Here is another approach with the same technique.
But in stead of a counter, you can give your own on-success string.
Remember to just replace the false/true with your conditions.
function dostuff($str) { echo $str; return true;}
false AND dostuff('string1') OR
false AND dostuff('string2') OR
false AND dostuff('string3') OR
true AND dostuff('string4') OR // echoes 'string4'
false AND dostuff('string5') OR
true AND dostuff('string6') OR // ignored
false AND dostuff('string7');

Categories