switch case isset triggered when case is -not- set - php

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

Related

PHP switch statement with preg_match

I have some problem to create a preg_match() inside my switch statement.
I want to write preg_match that match /oop/page/view/[some-number].
For now its working like:
If I run in my browser http://example.com/oop/page/view/1 its shows '404 page'.
And when I run some address for example http://example.com/oop/page/view/test or even /oop/test its run 2nd case and dont know yet how. For sure something is wrong in my regex expresion..
public function check(){
$url = filter_input(INPUT_GET, 'url');
switch ($url) {
case '':
echo 'HomePage';
break;
case preg_match('#^/oop/page/view/\d+$#', $url):
echo $url;
break;
default:
echo '404 page';
break;
}
}
What you should do instead is something like this:
switch (true) {
case preg_match(...):
I don't remember if switch in PHP is strict or loose comparison, but if it's strict, just put a !! in front of each case to convert it to boolean.
A switch statement compares each case expression to the original expression in the switch(). So
case preg_match('#^/oop/page/view/\d+$#', $url):
is analogous to:
if ($url == preg_match('#^/oop/page/view/\d+$#', $url))
This is clearly not what you want. If you want to test different kinds of expressions, don't use switch(), use if/elseif/else:
if ($url == '') {
echo 'Homepage';
} elseif (preg_match('#^/oop/page/view/\d+$#', $url)) {
echo $url;
} else {
echo '404 page';
}

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

Check if an array field is set in a switch statement

I have a switch statement set up which checks the value in an array field. I also want to perform slightly different logic if the array has no field with that name.
I can write the code like this, which works, but looks a little messy in my mind:
if (!isset($_GET['action']))
{
require('menu.html');
}
else
{
switch ($_GET['action'])
{
case 'debug':
require('core/actions/debug.php');
break;
case 'submit':
require('core/actions/submit.php');
break;
case 'admin':
header("Location: /login");
break;
}
}
But would it be possible for me to instead move the logic from the if statement and combine it with with my switch logic?
In JavaScript, I could do case undefined: ... as just one of the cases. Can I do something similar in PHP?
If $_GET['action'] is empty, or does have value, but its not any of the ones you want, you can do this.
switch ($_GET['action'])
{
.............
case "":
echo "empty or not setted";
break;
}
But if $_GET['action'] is not setted it will throw notices on every comparison (but it will enter in case '' anyway).
To not show the notices you could do:
switch (#$_GET['action'])
But please, don't do that!
You could do the super-switch-crazy way too:
switch(true){
case !empty($_GET['action']):
switch ($_GET['action'])
{
.............
}
break;
default:
echo "not setted or empty";
break;
}
Edit:
As #IQAndreas pointed out in the comments a interest solution could be:
switch (true)
{
case (!isset($_GET['action']):
require('menu.html');
break;
case ($_GET['action'] == 'debug'):
require('core/actions/debug.php');
break;
case ($_GET['action'] == 'submit'):
require('core/actions/submit.php');
break;
case ($_GET['action'] == 'admin'):
header("Location: /login");
break;
}
But the best way IMO to handle this situation is doing what you are already doing (checking if the var is empty or setted, before the switch..case)
if (isset($_GET['action'])){
switch ($_GET['action'])
{
.............
case "":
echo "empty";
break;
}
} else {
echo "not setted";
}

writng switch statement of an already made if-else statement in php

i amjust startingout in php, i wanted to know how we write the switch equivalent of the following if..else statement:
$op1 = array("12", "13", "14");
$op2 = array("15", "16", "17", "18");
//echo $op1[1];
if(count($op1)> count($op2)){
echo "wrong";
}
else{
echo "right";
}
//ouptput is "right"
i tried the switch in this, but got it all wrong. i tried this and it gave a huge error:
//switch for the if-else
switch (count($op1)>count($op2)){
case (false):
echo "it is false";
case (true):
echo "it is true";
in the output, both "it is true" and it is flase" are showing.
please give the right way to do this. Thanks
Foreach is used as in case of loop statement. I din find any loop hear.
If you have to get one by one all the values of the array you can use foreach.
foreach($array_val ad $val){
//you can use $val hear..
}
Hope this will help:
// Use switch for the if-else
switch (count($op1)>count($op2)) {
case FALSE:
echo "it is false";
break;
case TRUE:
echo "it is true";
break;
// default:
// default is not required here, as the result is either TRUE or FALSE
}

Categories