Switch statement unusual behaviour - php

echo get_option('bp-username-field'); and echo get_option('bp-email-field'); respectively outputs checked and 0. but with this code both the cases are running. i.e. both hello from username and hello from email are dispayed.
switch("checked")
{
case get_option('bp-username-field'):
echo 'hello from username';
case get_option('bp-email-field'):
echo 'hello from email';
...
}
And if i change switch("0") it only echoes hello from email. Also, with swith(0) both case are running. What is this behaviour?

You have to add a break after the case. If not all cases will be executed. That is normal behavior for switch Statements
switch("checked")
{
case get_option('bp-username-field'):
echo 'hello from username';
break;
case get_option('bp-email-field'):
echo 'hello from email';
...
}

You are probably missing break
switch("checked")
{
case get_option('bp-username-field'):
echo 'hello from username';
break;
case get_option('bp-email-field'):
echo 'hello from email';
break;
...
}
When the first case gets executed, then you need to break the switch. You need to introduce break to break execution of rest of the cases that follows the selected case.
When switch(0) was called, it is the final case (as of here), so it doesn't execute the one before the second case.

switch/case does loose comparison. That's mean that "checked" == 0 is true. What you want to do is:
switch(true)
{
case get_option('bp-username-field') === "checked":
echo 'hello from username';
case get_option('bp-email-field') === "checked":
echo 'hello from email';
...
}
But in a switch statement, the condition is evaluated only once and the result is compared to each case statement. This mean that after the first case is evaluate as true, all the other case will be executed until the end of the switch. What you really want it:
if (get_option('bp-username-field') === "checked") {
echo 'hello from username';
}
if (get_option('bp-email-field') === "checked") {
echo 'hello from email';
}

Because your statement is wrong;
you should compare the variable what ever it is inside switch(variable) to all those cases. for example.
$favcolor = "red";
switch ($favcolor) {
case "red":
echo "Your favorite color is red!";
break;
case "blue":
echo "Your favorite color is blue!";
break;
case "green":
echo "Your favorite color is green!";
break;
default:
echo "Your favorite color is neither red, blue, nor green!";
}

Related

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.

AJAX chat commands - if command doesn't exist, echo error

So I have this commands handling:
$message = the entered message.
public function handleCommands($message, $username)
{
//Variables we're going to use
$space = strpos($message, ' '); # The first space.
$command = trim(substr($message, 1, $space)); # The command after the slash
$name = substr($message, $space + 1); # The name after the command.
switch ($command)
{
case 'ban':
$this->ban($name, $username);
break;
case 'prune':
$this->prune($username);
break;
case '':
echo 'Please use a command!';
break;
case 'test':
try
{
$this->test($name);
}
catch (exception $r)
{
echo $r->getMessage();
}
break;
}
}
This basically will check for the command.
$command = the entered word after the slash ( " / " ).
Can you see
case '':
This basically checks if there is no command after the slash.
Question: I want the system to check aswell, if the command exists in the cases.
For example:
user wrote:
/hello
But that command doesn't exists, considering we only have case 'ban', case 'prune', case 'test' and case ''.
there is no case 'hello', so it will throw an error.
Is there a function that does this sort of thing? How can I do this?
I believe what you're looking for is a default: case.
Example:
<?php
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
}
?>
EDIT:
Fixed version of problem that was chatted about: http://privatepaste.com/bd34e7e63b
Use the case default:
switch ($command)
{
case 'ban':
$this->ban($name, $username);
break;
case 'prune':
$this->prune($username);
break;
case '':
echo 'Please use a command!';
break;
case 'test':
try
{
$this->test($name);
}
catch (exception $r)
{
echo $r->getMessage();
}
break;
default:
echo "That command does not exist.";
}

switch case isset triggered when case is -not- set

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

How do i get this or correct this PHP logic Working

I am creating a report with the data which calls the stored procedure and that procedure returns
various sections (1,2,3,4,5,6) with the data in each section.Now the sections may contain or may
not contain the data.This is how i have wriiten my logic
foreach($this->$dbresults as $row){
$var1 ='';
If($var1!=$row['section']){
switch($row['section']){
case '1':echo "some thing data";
break;
case '2':echo "some thing data";
break;
case '3':echo "some thing data";
break;
case '4':echo "some thing data";
break;
case '5':echo "some thing data";
break;
case '6':echo "some thing data";
break;
}
}
$var1=$row['section']
}
So here My problem if any one of the section is not present then that section case cannot be executed
.I mean How do i execute the section even if the section is not returned from the database
I guess you're already ordering your results by section. If your sections are really 1-n, you could put your switch() code into some runsections function and do this:
$var1=0; $lastsection=16;
foreach($this->dbresults as $row) {
If($var1!=$row['section']){
for($num=$var1+1; $num<$row['section']; $num++) runsections($num);
runsections($row['section']);
}
$var1=$row['section'];
}
for($num=$var1+1;$num<=$lastsection;$num++) runsections($num);
if your sections aren't sequential numbers you could create an array and check if they've all been executed
$sections=array('a'=>0,'b'=>0,'c'=>0,'d'=>0,'e'=>0);
If($var1!=$row['section']){
unset($sections[$row['section']]);
runsection($row['section']);
}
...
}
foreach($sections as $num) {
runsection($num);
}
edit: so the runsections() function would look like this:
function runsections($section) {
switch($section){
case '1':echo "some thing data";
break;
case '2':echo "some thing data";
break;
case '3':echo "some thing data";
break;
case '4':echo "some thing data";
break;
case '5':echo "some thing data";
break;
case '6':echo "some thing data";
break;
}
}
switch($x){
case '1':
echo "some thing 1";
break;
case '2':
echo "some thing 2";
break;
case 'N':
echo "some thing N";
break;
default:
echo "some thing else";
}
After your last case, insert:
default: echo "some error";
The break is optional since it's the last case in the switch statement. Also, The single quotes are also optional if you're looking for numeric options.
case 1: echo "something";
break;
Maybe I am not quite understanding exactly what you want. The following code should work in the following conditions:
You always want to display the 6
sections with either DB data or
non-DB data.
You do not need to display the same
section multiple times.
$sections = range(1, 6);
foreach($sections as $sectionNum) {
$sectionNum = (string) $sectionNum;
$foundSection = false;
foreach($this->dbresults as $row) {
if ($row['section'] == $sectionNum) {
echo "section #$sectionNum has DB data: " . $row['data'];
$foundSection = true;
break;
}
}
if (!$foundSection) {
echo "section #$sectionNum does not have DB data.";
}
}
Here's what I've got:
foreach($this->dbresults as $row){
if(isset($row['section'])){
switch($row['section']){
case '1':echo "some thing data";
break;
case '2':echo "some thing data";
break;
case '3':echo "some thing data";
break;
case '4':echo "some thing data";
break;
case '5':echo "some thing data";
break;
case '6':echo "some thing data";
break;
default:echo "some thing data";
break;
}
} else {
//Do something since no section data was stored
}
}
I added a default case, fixed the small php errors ($this->$dbresults is changed, using isset instead of !='') and added an else to your if to do something if the section isn't found.

php use switch without break;

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

Categories