Using of the switch operator - php

Is it legitimate to use the switch operator in such way, if I want to print the first not empty var in order a,b,c.
The only problem i see is result in case when some conditions will be true.
I've tested it on 5.6 and 7 versions of php
But will it not be depend on the version of php?
$a = '';
$b = '';
$c = 'c';
switch (true) {
case (!empty($a)) :
echo $a;
break;
case (!empty($b)) :
echo $b;
break;
default:
echo $c;
};

You are not relying on any undocumented behaviour here, and it is unlikely this will change in any future version of PHP.
The trick of using switch(true) is sometimes discussed as though it was an extra operator, but it's actually just a consequence of how switch statements work - each case condition is compared with the value in the switch with ==, so you're effectively checking $condition == true each time.
Your code:
switch (true) {
case (!empty($a)) :
echo $a;
break;
case (!empty($b)) :
echo $b;
break;
default:
echo $c;
}
It's equivalent to:
if (true == !empty($a)) {
echo $a;
goto end;
}
if (true == !empty($b)) {
echo $b;
goto end;
}
// fallback
echo $c;
// goto target
end:
Since you're not using any fall through, we can rewrite the goto parts with elseand elseif:
if (true == !empty($a)) {
echo $a;
}
elseif (true == !empty($b)) {
echo $b;
}
else {
echo $c;
}
And of course the true == is redundant as well:
if (!empty($a)) {
echo $a;
}
elseif (!empty($b)) {
echo $b;
}
else {
echo $c;
}
As long as every case has a corresponding break, these different pieces of code are guaranteed to be identical based on the fundamental definition of a switch statement. The last is by far the most common, and thus easiest for other people to read your code.
The big difference with switch is that you can "fall through" and combine cases in different ways. If you need to do this, then the switch (true) form may be useful. If you don't need it, you should probably avoid the risk of accidentally falling through by using a normal if-elseif chain.

$a = '';
$b = '';
$c = 'c';
if(!empty($a)){
echo $a;
}elseif (!empty($b)){
echo $b;
}else{
echo $c;
}
elseif is the best and general Way!

Related

Can ($a == 1 && $a == 2 && $a == 3) ever evaluate to true?

Similar to this question here which was intended for javascript, it has spawned off numerous spin-offs for various different languages. I'm curious if the following can ever evaluate to true in PHP:
($a == 1 && $a == 2 && $a == 3)
To follow up a bit more, it seems simply setting $a = true will yield the desired result (This was not the case for javascript, due to the way type casting works in both languages). A few answers (in javascript) worked with === as well, so in PHP with typechecking (===), can the following ever yield true?
($a === 1 && $a === 2 && $a === 3)
I just tried this:
$a = true;
echo ($a == 1 && $a == 2 && $a == 3);
and it echoed 1.
Because of the type casting and not type checking, 1, 2, 3 will be treated as true when compared to a boolean value.
Answer to the edit: No it can't be done.
Hackish method which #FrankerZ commented about:
Zero byte character = 0xFEFF
http://shapecatcher.com/unicode/info/65279
http://www.unicodemap.org/details/0xFEFF/index.html
$var  = "1";
$var = "2";
$ var = "3";
echo ($var  === "1" && $var === "2" && $ var === "3") ? "true" : "false";
This code runs with this character because the name $ var and $var  seems to be valid for the PHP compiler and with the appropiate font, it can be hidden. It can be achieved with Alt + 65279 on Windows.
Whilst not strictly in keeping with the question, this can be done if the ints are wrapped in quotes:
<?php
class A {
private static $i = 1;
public function __toString()
{
return (string)self::$i++;
}
}
$a = new A();
if($a == '1' && $a == '2' && $a == '3') {
echo 'yep';
} else {
echo 'nope';
}
I can't think of a case where strict comparison would ever yield true. === operator compares the types first, so there's no way to use any magic method wizardry.
For curiosity the closest i could get is to slightly modify the setting and hack the variable in a tick function. Since ticks are only incremeted per statement, we have to break the comparison to multiple statements for this to work.
$a = 1;
register_tick_function(function () use (&$a) {
++$a;
});
declare(ticks = 1) {
$a === 1 or exit(1);
$a === 2 or exit(1);
$a === 3 or exit(1);
}
echo "a = $a\n";
Try it online.

How to check `if` statement from database column like '$a > $b'

How to check if statement from database column like $a > $b or $a == $b or $a != $b or $a < $b
I got data from database in $row['condition']
$row['condition'] = '$a == $b';
or
$row['condition'] = '100 == 10';
in if statement I want to check
if($row['condition']){
echo 'true';
}else{
echo 'false';
}
I want to output
false
A way to do so is using eval() function. But as the manual says, this is very dangerous:
Caution:
The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.1
That said, this code can be used:
$row['condition'] = '$a == $b';
$a=10;
$b=20;
// Evaluate the condition using "return your_condition;"
if (eval( 'return ' . $row['condition'] . ';' ))
{
echo "true";
}
else
{
echo "false";
}
Test it here.
1http://php.net/manual/en/function.eval.php

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

Using variables in if statements

PHP novice here. I searched for this, but i'm sure i'm not using the right syntax regarding my issue. Apologies then if this is a duplicate:
I have these 3 variables:
$param = get_sub_field('custom_parameter');
$compare = get_sub_field('parameter_compare');
$param_val = get_sub_field('parameter_value');
each one would return this:
$param is 'my_parameter'
$compare is either '==', '<=', or '=>'
$param_val is something like '5' or any value that the user sets
What i have is an editing interface where the user can set their parameter name, set the compare and then add the value. To that they can also add an action that occurs if the parameter matches. I'm using this in conjunction with $_GET.
What i'd like to do is insert each variable from above into my if statement so the comparison is created by the user. However, it keeps giving me an error when i try to do this:
if($_GET[$param] $compare $param_val) {
// do something
}
The error i get is:
Parse error: syntax error, unexpected T_VARIABLE
This of course works just fine:
if($_GET[$param] == $param_val) {
// do something
}
Hopefully i've explained this well enough and any help is greatly appreciated.
Update: Thank you for answering this for me and jumping on it so quickly. Learned a ton here!!
function comparer($param, $compare, $param_val)
{
switch ($compare){
case '==': return $param == $param_val;
case '!=': return $param != $param_val;
case '<=': return $param <= $param_val;
case '>=': return $param >= $param_val;
case '<': return $param < $param_val;
case '>': return $param > $param_val;
default: return FALSE;
}
}
/* ... */
if (comparer($param, $compare, $param_val)){
// true
}
Very simple method to get you going. I would, at all costs, resist the temptation to use eval, unless you want to invest a lot of time in sanitizing those three parameters.
Oh, and an example
I think I would use a switch statement to avoid any scary eval code.
Such as:
switch($compare) {
case '==':
if($_GET[$param] == $param_val) {
// do something
}
break;
case '<=':
if($_GET[$param] <= $param_val) {
// do something
}
break;
case '>=':
if($_GET[$param] <= $param_val) {
// do something
}
break;
}
Look at eval()
http://php.net/manual/en/function.eval.php
With this you can parse a code you format in a string.
The best way would be to make a function for this. Have that function uses a switch to determine the operator, then return the comparison.
function compare($a, $b, $operator){
$ret = NULL;
switch($operator){
case '==':
$ret = $a == $b;
break;
case '>=':
$ret = $a >= $b;
break;
case '<=':
$ret = $a <= $b;
break;
}
return $ret
}
Then just simply call it:
if(compare($_GET[$param], $param_val, $compare)){
// do something
}
Hmm interesting, I think I'd approach it like this (untested):
function comparison($param, $compare, $param_val) {
if ($compare == '==') {
if ($param == $param_val) {
return true
}
}
if ($compare == '<=') {
if ($param <= $param_val) {
return true
}
}
if ($compare == '>=') {
if ($param >= $param_val) {
return true
}
}
}
Not very efficient or DRY, could probably use a switch as that would probably be better but this was the first thing to pop into my head.
Usage
if (comparison($param, $compare, $param_val)) {
echo 'it's true';
} else {
echo 'it's false';
}
Edit
As per usual, I have been beaten to the punch by better code :)
P.S. I'm not sure why you have $param and then use $_GET[$param] so I've just used $param in my answer.

Restart an if else construct

Let's take a look at the following code:
if ($a == 1) {
echo "this is stage 1";
}
else if ($a == 2) {
echo "this is stage 2";
}
else if ($a == 3) {
$a = 1;
// at this point I want something that restarts the if-else construct so
// that the output will be "this is stage 1"
}
I'm working on an if else construct at the moment and let's say that I have three stages and the if-else construct checks which stage I'm in.
Now it happens that some activities in stage 3 lead to a jump back to stage 1. Now I've already passed the code for stage one, which is why I want to somehow restart the if-else construct. Is there a way to do that? And even more important: Is there a better way to do what I want? Because my idea doesn't seem to be good practice.
You're right, it's bad practice.
You're asking for goto.
Example:
<?php
goto a;
echo 'Foo';
a:
echo 'Bar';
The above would never output 'Foo'
It's difficult to suggest the better method without seeing exactly what you're trying to do, but consider a switch.
switch ($a) {
case 3:
// Execute 3 stuff
// No break so it'll continue to 1
case 1:
// Execute 1 stuff
break // Don't go any further
case 2:
// 2 stuff
break;
}
That's probably not what you want either.
You may just want to abstract the code into functions and call them multiple times if necessary.
You can put an endless loop around your if and break out if you're done
while (1) {
if ($a == 1) {
echo "this is stage 1";
break;
}
else if ($a == 2) {
echo "this is stage 2";
break;
}
else if ($a == 3) {
$a = 1;
}
else {
break;
}
}
Maybe you want to look at Wikipedia - Finite-state machine and this question PHP state machine framework
The short answer is yes, there is a way, but the better answer is yes to your second question as well.
Put, at very least, the code that can get called from multiple locations in a function. For example,
function stageOneCode() {
//do stuff;
}
etc.. I would recommend a function for each stage, but it's hard to make recommendations without actually seeing what's being executed in the stages.
In any event, at the end of your stage three function, simply call your stage one function.
A recursive function is helpful for this (but maybe overkill if it will always revert back to 1)
function echo_stage($stage) {
if ($a == 1) {
return "this is stage 1";
}
else if ($a == 2) {
return "this is stage 2";
}
return echo_stage(1);
}
echo echo_stage(5);
Or:
switch ($number)
{
case 2 :
echo "this is stage 2";
break;
case 1:
default:
echo "this is stage 1"
}
use switch(). you can have a "default" case as well as specific cases.
A loop is what you are searching for:
// initialize $a
$a = 1;
// the while loop will return endless
while (true);
// if you want to break for any reason use the
// break statement:
// if ($whatever) {
// break;
// }
if ($a == 1) {
echo "this is stage 1";
}
else if ($a == 2) {
echo "this is stage 2";
}
else if ($a == 3) {
$a = 1;
// continue will go back to the head
// of the loop (step 1) early:
continue;
}
// don't forget to increment $a in every loop
$a++;
}

Categories