whats wrong with my switch ?
Now result:
< more
> less
= equality
!= no't equality
As it should be:
< more
= equality
<?php
$page = 99;
switch ($page)
{
case $page < 121:
echo '< more <br/>';
case $page > 123:
echo '> less <br/>';
case $page == 99:
echo '= equality <br/>';
case $page != 99:
echo '!= no\'t equality <br/>';
}
?>
In your switch statement you're comparing a number with boolean values.
Let's take the first case $page < 121 is true, so the comparison taking place is 99==true which is true according to http://docs.php.net/language.types.type-juggling (switch performs a loose comparison, not a strict like ===). Thus the first case block is executed.
And since you don't have a break statement it falls through to the next case block and the next and so on...
Meaning: This won't work as intended regardless of whether you use break or not.
You don't seem to understand how switch works. What you want is a series of if statements, i.e.
if ($page < 121)
echo '< more <br/>';
if ($page > 123)
echo '> less <br/>';
if ($page == 99)
echo '= equality <br/>';
if ($page != 99)
echo '!= no\'t equality <br/>';
Switch is to be used only when you want to compare a variable against a set of values.
switch ($variable)
{
case "me":
echo "variable is me";
break;
case "you":
echo "variable is you";
break;
default:
echo "Variable is neither of us";
}
The above switch case block can be written as shown below:
if ($variable=="me")
{
echo "variable is me";
}
elseif ($variable=="you")
{
echo "variable is you";
}
else
{
echo "variable is neither of us";
}
DO NOT put an expression near the case statement.
switch ($somethng)
{
case $something < 10:
break;
case $something > 20:
break;
}
Switch is meant to be used only for comparing a variable against a set of values. ONLY! For everything else use a if...elseif..else statement.
The block above is wrong usage. Sometimes more than one of those expressions could be true.
$var = "cat";
switch($var)
{
case "cat":
echo 'My '.$var.' is called Bob.';
break;
case "dog":
echo 'My '.$var.' is called James.';
break;
default:
echo "I don't have an animal";
break;
}
In a switch statemant you compare $var against value in a case. If there is a match, the actual case will be executed, otherwise the default will be executed. You can't use <>!=... in a case, only values like: 1, '1', 'dog', $var2, and so on.
If you want to run the same command for two case you can do:
$var = "cat";
switch($var)
{
case "cat":
case "dog":
echo 'My '.$var.' is called James.';
break;
default:
echo "I don't have an animal";
break;
}
In your code, your forgot to put break; at the end of each case, that's why you see 'everything' in your output. And you miss default: too.
For the task you're doing, i suggest you to use if statements.
if iam not wrong you can't use this characters < > raw in html. use instead the entities > and <.
if you run the script in the command line i got following output.
<?php
ob_start();
$page = 99;
switch ($page)
{
case $page < 121:
echo '< more <br/>';
case $page > 123:
echo '> less <br/>';
case $page == 99:
echo '= equality <br/>';
case $page != 99:
echo '!= no\'t equality <br/>';
}
$buffer = ob_get_clean();
echo str_replace('<br/>', "\n", $buffer);
output
< more
> less
= equality
!= no't equality
which seems to be the correct behavoir.
It is important to understand how the
switch statement is executed in order
to avoid mistakes. 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.
http://de.php.net/manual/de/control-structures.switch.php
';
break;
case $page > 123:
echo '> less ';
break;
case $page == 99:
echo '= equality ';
break;
case $page != 99:
echo '!= no\'t equality ';
break;
default: echo 'Default';
}
?>
Related
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.
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 ;
}
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;
}
--Let me add this. This code works for me the way it is. I just do not know why it works.--
I can't figure this out.
switch ($_SERVER['QUERY_STRING']) {
case isset($_GET['test0']):
echo "test0<br>";
break;
case isset($_GET['test1']):
echo "test1<br>";
break;
case isset($_GET['test2']):
echo "test2<br>";
break;
case isset($_GET['test3']):
echo "test3<br>";
break;
case isset($_GET['test4']):
echo "test4<br>";
break;
default:
echo "no test<br>";
break;
}
When the url is index.php?test0, "test0" is shown.
When the url is index.php?test4, "test4" is shown.
When the url is index.php?test999, "no test" is shown.
When the url is index.php?tes, "no test" is shown.
When the url is index.php?, or index.php, "test0" is shown.
Why is this? The condition is not met, so should the default not be shown?
switch can't be used this way. isset() returns true or false, not something (a string, an int, etc) you can match against. What you are basically doing is:
switch ($_SERVER['QUERY_STRING']) {
case true:
echo "test0<br>";
break;
case true:
echo "test1<br>";
break;
case false:
echo "test2<br>";
break;
case false:
echo "test3<br>";
break;
case true:
echo "test4<br>";
break;
default:
echo "no test<br>";
break;
}
cases are considered from top to bottom. In this case, $_SERVER["QUERY_STRING"] is automatically type-converted to bool (which will return true in this case). The first case it sees would be test0, so it echos that. If you do that for test0-4, it will give you the false illusion that this code is working as intended, while it's not considering the edge cases.
The only way you can achieve what you want is by using multiple ifs, or by redesigning your application.
When the url is index.php?, or index.php, "test0" is shown.
Why is this? The condition is not met, so should the default not be shown?
Like a good question, your question as well contains the answer already.
You already have realized that the condition must be met even you think it is not met. Therefore you ask. So let's see which condition is met:
case isset($_GET['test0']):
echo "test0<br>";
break;
This is a test for isset($_GET['test0']) and we know with the request that this is FALSE. So this test tests for FALSE.
Now let's see against what this tests:
switch ($_SERVER['QUERY_STRING']) {
That is $_SERVER['QUERY_STRING']. So if $_SERVER['QUERY_STRING'] is FALSE the test0 will be output.
Because switch { case:} in PHP does loose comparison, the empty string $_SERVER['QUERY_STRING'] is FALSE. This is why you see the output.
Easy if you know why, right? And all so logical.
And what you wanted to test against was not $_SERVER['QUERY_STRING'] but just TRUE:
switch (TRUE)
{
case isset($_GET['test0']) :
...
}
This gets the job done, too.
<?php
$q = $_SERVER['QUERY_STRING'];
if(!empty($q) && isset($q) && strlen($q) >0 ){
$url = $q;
switch ($url){
case true;
echo $url;
break;
}
}
else {
echo "no test<br>";
}
what about
$found = false;
for($i=0;$i <=4; $i++){
if( isset($_GET['test'.$i]) ){
echo "test".$i;
$found = true;
}
}
if(!$found){
echo "no test";
}
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');