Unexpected results using dynamic variables - php

The following code using switch and dynamic variables should return "b1" but it returns "11".
Is this a bug or am I doing something wrong?
<?php
$d = "Tuesday";
switch($d) {
case "Monday":
$$previousdayofmonthrow = "a";
$$previousdayofmonthcol = "7";
break;
case "Tuesday":
$$previousdayofmonthrow = "b";
$$previousdayofmonthcol = "1";
break;
case "Wednesday":
$$previousdayofmonthrow = "b";
$$previousdayofmonthcol = "2";
break;
case "Thursday":
$$previousdayofmonthrow = "b";
$$previousdayofmonthcol = "3";
break;
case "Friday":
$$previousdayofmonthrow = "b";
$$previousdayofmonthcol = "4";
break;
case "Saturday":
$$previousdayofmonthrow = "b";
$$previousdayofmonthcol = "5";
break;
case "Sunday":
$$previousdayofmonthrow = "b";
$$previousdayofmonthcol = "6";
break;
}
echo $$previousdayofmonthrow;
echo $$previousdayofmonthcol;
?>
Live example > http://codepad.org/wNfCqffD

tldr; It is not a bug in PHP related to dynamic variables, nor is it related with the switch statement.
The behavior of the test-case is correct and is well-defined, even if not expected.
This is because both $previousdayofmonthrow and $previousdayofmonthcol evaluate to undefined (did have notices enabled, no?) and thus both "dynamic variables" (aka variable-variable) expressions operate on the same variable.
Here is a minimal reproduction of the the behavior, without a switch, that also shows some interesting intermediate values:
$x = undefined; // The original doesn't set a value; it is implicitly undefined
$y = undefined; // but the effect is the same, and this way avoids warnings - yay!
$$x = "a";
echo $$x; // -> "a"
echo $$y; // -> "a"
$$y = "b";
echo $$x; // -> "b"
echo $$y; // -> "b"
This "linked" behavior occurs because, as previously stated, the variable-variable expression access the same variable - mainly the variable called "undefined". (The value of the expression used as the dynamic variable name is turned into a string and "" . undefined -> "undefined"):
echo ${"undefined"}; // -> "b"
This "assignment of undefined" is allowed because undefined in PHP is a reserved word - and not a constant/variable. Thus it is not prohibited to use "undefined" as a variable name even though it cannot appear as an unquoted identifier.
FWIW: Consider not using variable-variables; it is almost always better to use a discrete array when such "dynamic keys" are required.

Related

php if and elseif statements with multiple/more than 3 conditions [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I want to assign random profile pictures to users when they register on a website. I have a problem with my code. If I limit the "if and elseif" statements to 2 conditions, it works well. But when I go over 2 (in this case I have 10 conditions), the code doesn't work. If "switch" statement should be used instead, how would you write the code?
Here is my code
$rand = rand(1,10); //random number between 1 and 10
if($rand == 1)
$profile_pic = "/defaults/profile_pic1.png";
else if($rand == 2)
$profile_pic = "/defaults/profile_pic2.png";
.
.
.
else if($rand == 9)
$profile_pic = "/defaults/profile_pic9.png";
else
$profile_pic = "/defaults/profile_pic10.png";
I hope that's what you want
<?php
$rand = rand(1,10);
switch ($rand) {
case "1":
$profile_pic = "/defaults/profile_pic1.png";
echo "1";
break;
case "2":
$profile_pic = "/defaults/profile_pic2.png";
echo "2";
break;
case "3":
$profile_pic = "/defaults/profile_pic3.png";
echo "3";
break;
case "4":
$profile_pic = "/defaults/profile_pic4.png";
echo "4";
break;
case "5":
$profile_pic = "/defaults/profile_pic5.png";
echo "5";
break;
case "6":
$profile_pic = "/defaults/profile_pic6.png";
echo "6";
break;
case "7":
$profile_pic = "/defaults/profile_pic7.png";
echo "7";
break;
case "8":
$profile_pic = "/defaults/profile_pic8.png";
echo "8";
break;
case "9":
$profile_pic = "/defaults/profile_pic9.png";
echo "9";
break;
case "10":
$profile_pic = "/defaults/profile_pic10.png";
echo "10";
break;
default:
$profile_pic = "/defaults/profile_picDEFAULT.png";
echo "default PHOTO";
}
?>
I really do not understand why you would want to use a switch statement here. In terms of improving the code - you could go with only 2 lines. With if and switch it's 2-3 lines per condition and it's the worst programming practice you might come up with. Just give me a good reason why.
If you read PHP documentation thoroughly, there is the String Operators page available, which explains how your problem might be solved:
concatenation operator (.), which returns the concatenation of its right and left arguments.
$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"
So you could simply do it with
$rand = rand(1,10);
$profile_pic = "/defaults/profile_pic" . $rand . ".png";
Or you might stumble upon Variable parsing, which states:
When a string is specified in double quotes or with heredoc, variables are parsed within it.
$juice = "apple";
echo "He drank some $juice juice.".PHP_EOL;
// Invalid. "s" is a valid character for a variable name, but the variable is $juice.
echo "He drank some juice made of $juices.";
// Valid. Explicitly specify the end of the variable name by enclosing it in braces:
echo "He drank some juice made of ${juice}s.";
So what you could do is:
$rand = rand(1,10);
$profile_pic = "/defaults/profile_pic${rand}.png";
If you are using the same random number in image path then no need for if or switch loop.
You can use below code.
$rand = rand(1,10) ;
$profile_pic = "/defaults/profile_pic$rand.png";
If you have mapping of random number and images then store it in array and access it.
$rand_image = array(1=>"firstimg.png", 2=>"2.png") ;
$profile_pic = "/defaults/profile_pic".$rand_image[$rand];
<?php
if (condition) {
code to be executed if this condition is true;
} elseif (condition) {
code to be executed if first condition is false and this condition is true;
} else {
code to be executed if all conditions are false;
}
?>

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

SWITCH returns TRUE when comparing letters to numbers. WHY?

Short question: WHY?!?
The below class returns ALL ALLRIGHT when calling:Status::validate('ab')
class Status
{
const FRESH = 0;
const PENDING = 25;
const CANCELLED = 50;
public static function validate($status)
{
switch ($status) {
case self::FRESH:
case self::PENDING:
case self::CANCELLED:
echo 'ALL ALLRIGHT';
default:
echo 'ERROR!';
}
die;
}
}
I believe it's because your $status is being casted to int.
$value = 'abc';
$other_value = '21abc';
echo (int)$value;
echo '<br>';
echo (int)$other_value;
Will return:
0
21
And that would cause it to think that ab value is equal to Status::FRESH
I'm not sure though if switch statement does this type of typecasting.
Edit
And I think I was right. More info here PHP Manual - switch.
Reference on typecasting strings to integers here PHP Manual - Strings.
break the case
switch($condition){
case "options": blah(); break;
}

Variable scope in php in 2 block codes

In a webpage in top i use this code:
<?php
switch ($urlcomecatid) {
case "95":
$target_cat1='96';
$target_cat1_name = "A";
break;
case "96":
$target_cat1='95';
$target_cat1_name = "B";
break;
?>
and in another down part the page i use these variable
<?php
echo "<p class='pagefooterlifestyle' align='center'>
<a href='../lifestyle/lifestylesub.php? catid=$target_cat1'>$target_cat1_name</a></p>";
?>
BUT i get error undefined variable for
$target_cat1
$target_cat1_name
please let me know that what is the problem?
Initialize your variables:
switch ($urlcomecatid) {
case "95":
$target_cat1='96';
$target_cat1_name = "A";
break;
case "96":
$target_cat1='95';
$target_cat1_name = "B";
break;
default:
$target_cat1 = '';
$target_cat1_name = '';
}
You must be prepared for different values for $urlcomecatid as well.
If your $urlcomecatid variable contains neither 95 nor 96, PHP will ignore both cases, so the $target_cat1 and $target_cat1_name variables won't be initialized.
You can use default to tell PHP what to do when all cases are ignored.
http://php.net/manual/fr/control-structures.switch.php

Assign result of function within switch to variable

here's some pseudo-code (it's not written correctly, the point of my ? is the variable, not the switch):
switch ($action) {
case "1":
//this is a function
case "2":
//this is a function
//etc.
}
How should this be written:
$variable = result of function in case 1.
Your switch statement is wrong . It requires a break keyword between every case
$action = 1;
$result = "Success";
switch ($action) {
case 1:
$variable = $result;
echo $variable;//prints Success
//this is a function
break; // like this
case 2:
//this is a function
break;//
//etc.
}
Just run the function(s) (you can pass args in too) as part of the code within the case / break blocks like this :
$action = 1;
switch ($action) {
case 1:
$variable = someFunctionOne();
break;
case 2:
$variable = someOtherFunctionTwo();
break;
//etc.
}
how to variable the result of php switch.
ex:
<?php
//variables of cases
$var_1 = 1;
$var_2 = 2;
$var_3 = 3;
$var_0 = 0;
//end variables of cases
//action variable
$action = 10;
//end action variable
//start switch
switch ($action) {
case "1":
echo "$var_1;";
break;
case "2":
echo "$var_2;";
break;
case "3":
echo "$var_3;";
break;
default:
echo "$var_0;";
}
//receives the value of the switch.
$switch_result = get_result_case;
//in this my example I need to enter the value of the case in a variable.
?>
in this my example I need to enter the value of the case in a variable.

Categories