I have three variables which determine an outcome. There is only two outcomes but the outcome is based on the variables. I have thought up some long if statements but I am wondering if there is a cleaner way to do it.
$loggedin = (0 or 1) // If it is 0 then one outcome if 1 then it falls onto the next three variables
$status = (0-5) // 4 dead ends
$access = (0-3) //
$permission = (0-9)
Different combinations of the last two variables result in different outcomes, although some combinations are irrelevant as they are dead ends.
if ($loggedin == 1 && ($status == 1 || $status == 2 ) && 'whattodohere' ):
I could type all of the combinations manually ($access == 0 && ($var == 2 || $var = 6)) but I am wondering if there is a better way of doing this that I am unaware of.
Have a look at bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) - http://php.net/manual/en/function.in-array.php
Also take a look at range(...) - http://php.net/manual/en/function.range.php
$status == 1 || $status == 2 [... $status == n] can be reduced to in_array( $status, range(0, $n) )
Using in_array & range is more costly performance-wise tho, so if you're dead sure you only need to try against 2 different values, use == operator instead.
An approach could to be to use switch(): http://php.net/manual/en/control-structures.switch.php
Example:
<?php
/*
$loggedin = (0 or 1) // If it is 0 then one outcome if 1 then it falls onto the next three variables
$status = (0-5) // 4 dead ends
$access = (0-3) //
$permission = (0-9) */
$access = 1;
$loggedin = 1;
$status = 1;
if ($loggedin == 1) {
if ($status == 1 || $status == 2 ) {
switch($access) {
case 0:
//do some coding
break;
case 1:
echo 'ACCESSS 1';
//do some coding
break;
default:
//Do some coding here when $access is issued in the cases above
break;
}
}
}
else {
//Do coding when $loggedIn = 0
}
?>
In the example ACCESS 1 would be the output.
Maybe you could also do some math and compare the result (in some circumstances depending on what you want to achieve). For example:
<?php
$permission = 1;
$access = 2;
$result = $permission * $access;
if ($result > 0) {
switch($result) {
case 0:
//do something
break;
case 1:
//do something
break;
default:
//Do something when value of $result not issued in the cases above
}
}
?>
Related
I am trying to compare two statements in PHP. After that I need to check if their output is true or false.
I will start by explaining with a little example for more clarifications.
let's say we have:
$statement1 = '(p == 5 || p == 8) && (r == 01 || r == 06)';
$statement2 = '(p == 5)(r == 01)'; // yes, it doesn't contain an &&
I need to compare $statement2 with $statement1 and have the result as true because (p == 5) in $statement2 is true according to the first part of $statement1 (p == 5 || p == 8) AND (r == 01) in $statement2 is true according to the second part of $statement1 (r == 01 || r == 06). So in a nutshell, I should get a true for those statements.
So what I thought of is to take the value between parentheses of the two statements and store them in arrays with the following code
PS: $text_outside was created in case it's needed
function extract($string)
{
$text_outside=array();
$text_inside=array();
$t="";
for($i=0;$i<strlen($string);$i++)
{
if($string[$i]=='(')
{
$text_outside[]=$t;
$t="";
$t1="";
$i++;
while($string[$i]!=')')
{
$t1.=$string[$i];
$i++;
}
$text_inside[] = $t1;
}
else {
if($string[$i]!=')')
$t.=$string[$i];
else {
continue;
}
}
}
if($t!="")
$text_outside[]=$t;
return $text_inside;
}
That will be applied for both statements. I will then loop through the arrays created for the comparison. but then I am stuck. I am unable to compare both statements to get if it's true or false.
That's the remaining part:
$extractedStatement1[] = extract($statement1);
$extractedStatement2[] = extract($statement2);
foreach ($statement2 as $val2){
foreach ($statement1 as $val1){
//I am stuck here
}
}
I need to get at the end if the $statement2 is true or false according to $statement1. I am open to other approaches as well.
You could use Symfony's ExpressionLanguage component after transforming $statement2 into a var -> value associative array:
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
$statement1 = '(p == 5 || p == 8) && (r == 01 || r == 06)';
$statement2 = '(p == 5)(r == 01)';
$assignments = [];
if (preg_match_all('/\((\w+) == (\w+)\)/', $statement2, $matches, PREG_SET_ORDER)) {
foreach ($matches as [, $var, $val]) {
$assignments[$var] = $val;
}
}
$expressionLanguage = new ExpressionLanguage();
var_dump($expressionLanguage->evaluate($statement1, $assignments)); // true
Demo
Edit: if you need to handle != too then the following should do:
$assignments = [];
if (preg_match_all('/\((\w+) ([!=])= (\w+)\)/', $statement2, $matches, PREG_SET_ORDER)) {
foreach ($matches as [, $var, $operator, $val]) {
$assignments[$var] = $operator === '=' ? $val : null;
}
}
if($_SESSION['valueofdie1'] != 0 && $_SESSION['valueofdie2'] != 0 && $_SESSION['valueofdie3'] != 0 && $_SESSION['valueofdie4'] != 0 && $_SESSION['valueofdie5'] != 0)
{
if((($_SESSION['valueofdie1'] == $_SESSION['valueofdie2']) && ($_SESSION['valueofdie2'] == $_SESSION['valueofdie3']||$_SESSION['valueofdie4']||$_SESSION['valueofdie5'])) || (($_SESSION['valueofdie1'] == $_SESSION['valueofdie3']) && ($_SESSION['valueofdie3'] == $_SESSION['valueofdie4']||$_SESSION['valueofdie5'])) || (($_SESSION['valueofdie1'] == $_SESSION['valueofdie4']) && ($_SESSION['valueofdie4'] == $_SESSION['valueofdie5']))
|| (($_SESSION['valueofdie2'] == $_SESSION['valueofdie3']) && ($_SESSION['valueofdie3'] == $_SESSION['valueofdie4']||$_SESSION['valueofdie5'])) || (($_SESSION['valueofdie2'] == $_SESSION['valueofdie4']) && ($_SESSION['valueofdie4'] == $_SESSION['valueofdie5']))
|| (($_SESSION['valueofdie3'] == $_SESSION['valueofdie4']) && ($_SESSION['valueofdie4'] == $_SESSION['valueofdie5'])))
{
if($_POST['choose'] == 'choose 3oaK')
{
$_SESSION['g'] = 5;
$_SESSION['scoretkind'] = $_SESSION['valueofdie1'] + $_SESSION['valueofdie2'] + $_SESSION['valueofdie3'] + $_SESSION['valueofdie4'] + $_SESSION['valueofdie5'];
unset($_SESSION['3oaKBut']);
echo '<input type="hidden" name="choose" value="Clear" onLoad="form.submit();">';
$_POST['sub'] = 'reset';
$_POST['choose'] = '';
}
if(empty($_SESSION['g']))
{
$_SESSION['3oaKBut'] = '<input type="submit" name="choose" value="choose 3oaK">';
echo $_SESSION['3oaKBut'];
}
}
}
if($_SESSION['g'] == 5)
{
echo $_SESSION['scoretkind'];
}
So here is the code we have. We are trying to check if 3 of the 5 die values are equal. If they are equal we echo out a button that allows the user to choose to score his 3 of a kind, which is the total of all of the dice. Everything works except in some cases the 3 of a kind button would echo out when there isnt a 3 of a kind. Halp PLS
I'm sorry I didn't answer your question by actually solving your bug, but I think your code is hard to read and your approach makes it cumbersome to program all the rules.
General advice: Put $_SESSION['valueofdie1'] and the other dice into an array of values. That's much easier to work with. After that, it should be pretty easy to check how many times each value occurs. Even when you keep your approach, you could make variables like $die1, which is already a lot shorter and more readable than $_SESSION['valueofdie1'].
But with an array, you could roughly start like this:
// Put all dice into an array.
$dice = array(
$_SESSION['valueofdie1'],
$_SESSION['valueofdie2'],
etc.... );
// Count how many times each die is rolled.
$diceCount = array();
foreach($dice as $die) {
$count = 0;
if (isset($diceCount[$die])) {
$count = $diceCount[$die];
}
$diceCount[$die] = $count + 1;
}
// Check possible results simply by looking at those counts.
// If one die value is rolled 5 times, it's Yahtzee...
if (array_search(5, $diceCount) !== false) {
echo 'Yahtzee!';
}
if (array_search(4, $diceCount) !== false) {
echo 'Four of a kind';
}
// Full house takes two types.
if (array_search(3, $diceCount) !== false && array_search(2, $diceCount) !== false) {
echo 'Full house';
}
for ($diceCount as $die => $count) {
echo "$count times $die";
}
... etc ...
You'll need to expand this list, and take some other rules into account. After all, a Yahtzee could also count as a Four of a Kind. But by checking all those rules, you can generate a new array of possible combinations, which you can check against the previously chosen options. And the outcome of that determines which options the player can choose.
I have string $a,$b,$c
I know if all of them not null express in this way:
if($a!="" && $b!="" && $c!="")
But if either 2 of them not null then go into the true caluse
if($a!="" && $b!="" && $c!=""){
** do the things here **
}else if(either 2 are not null){
**do another things here**
}
How to express it?
I would write a simple function like this to check:
function checkInput($var)
{
$nulls=0;
foreach($var as $val)
{
if(empty($val))
{
$nulls++;
}
}
return $nulls;
}
Then access it like this:
$inputs=array($a, $b, $c.... $z);
$nullCount=checkInput($inputs);
if($nullCount==0)
{
// All nulls
}
if($nullCount>2)
{
// More than 2 nulls
}
or for an one-off test, just pop the function into the actual if statement like this:
if(checkInput($inputs)>2)
{
// More than 2 nulls...
}
etc etc. You can then use the one function to check for any number of nulls in any number of variables without doing much work - not to mention change it without having to rewrite a long if statement if you want to modify it.
Other answers are good, but you can expand this to easily handle more variables:
$variables = array($a, $b, $c, $d, ....);
$howManyNulls = 0;
foreach($variables as $v){
if($v == ''){
$howManyNulls++;
}
}
if($howManyNulls == count($variables) - 2){
// do stuff
}
you can try this
if($a!="" && $b!="" && $c!="")
{
** do the things here **
}
else if(($a!="" && $b!="") || ($b!="" && $c!="") || ($a!="" && $c!=""))
{
**do another things here**
}
Try:
if($a!="" && $b!="" && $c!=""){
** do the things here **
}else if(($a!="" && $b!="") || ($a!="" && $c!="") || ($b!="" && $c!="")){
**do another things here**
}
$var[] = empty($a) ? 0:$a;
$var[] = empty($b) ? 0:$b;
$var[] = empty($c) ? 0:$c;
$varm = array_count_values($var);
if ($varm[0] === 0) {
//Code for when all aren't empty!
} elseif ($varm[0] === 1) {
//Code for when two aren't empty!
}
N.B; You may need to replace the 0 for a string/integer that will never crop up, if your variables are always strings or empty then 0 will do for this. The method for using bools within this would require more code.
$nullCount = 0
if($a!=""){ ++$nullCount; }
if($b!=""){ ++$nullCount; }
if($c!=""){ ++$nullCount; }
if($nullCount == 3){ // all are null
// do smth
}else if($nullCount == 2){ // only two are null
// do other
}
Just for fun, here's something potentially maintainable, should the list of arguments increase:
function countGoodValues(...$values) {
$count = 0;
foreach($values as $value) {
if($value != "") {
++$count;
}
}
return $count;
}
$goodValues = countGoodValues($a, $b, $c); // Or more... or less
if($goodValues == 3) {
// Do something here
}
else if($goodValues == 2) {
// And something else
}
Reference for the ... construct (examples #7 and #8 in particular) are available on php.net.
You can use double typecasting (to boolean, then to number) in conjunction with summing:
$count = (bool)$a + (bool)$b + (bool)$c;
if ($count == 3)
// ** do the things here **
else if ($count == 2)
//**do another things here**
There is also possible such solution:
<?php
$a= 'd';
$b = 'a';
$c = '';
$arr = array( (int) ($a!=""), (int) ($b!=""), (int) ($c!=""));
$occ = array_count_values($arr);
if ($occ[1] == 3) {
echo "first";
}
else if($occ[1] == 2) {
echo "second";
}
If you have 3 variables as in your example you can probably use simple comparisons, but if you have 4 or more variables you would get too big condition that couldn't be read.
if (($a!="") + ($b!="") + ($c!="") == 2) {
// two of the variables are not empty
}
The expression a!="" should return true (which is 1 as an integer) when the string is not empty. When you sum whether each of the strings meets this condition, you get the number of non-empty strings.
if (count(array_filter([$a, $b, $c])) >= 2) ...
This is true if at least two of the variables are truthy. That means $var == true is true, which may be slightly different than $var != "". If you require != "", write it as test:
if (count(array_filter([$a, $b, $c], function ($var) { return $var != ""; })) >= 2) ...
if($a!="" && $b!="" && $c!="") {
echo "All notnull";
} elseif(($a!="" && $b!="") || ($b!="" && $c!="") || ($a!="" && $c!="")) {
echo "Either 2 notnull";
}
Basically I have this code scenario:
if($_SESSION['player_1_pawn'][0]['currentHealth'] <=0 &&
$_SESSION['player_1_pawn'][1]['currentHealth'] <=0 &&
$_SESSION['player_1_pawn'][2]['currentHealth'] <=0 &&
$_SESSION['player_1_pawn'][3]['currentHealth'] <=0 &&
$_SESSION['player_1_pawn'][4]['currentHealth'] <=0) {
//some code here
}
Is there any way to check or to loop through all of the indexes if all of ['player_1_pawn'][index]['currentHealth'] is smaller than 0, instead of writing it one by one like I posted?
Just write a foreach construct that loops through all of the array elements you need to check:
$flag = true; // after the foreach, flag will be true if all pawns have <= 0 health
foreach ($_SESSION['player_1_pawn'] as $value)
{
// for each pawn, check the current health
if ($value['currentHealth'] > 0)
{
$flag = false; // one pawn has a positive current health
break; // no need to check the rest, according to your code sample!
}
}
if ($flag === true) // all pawns have 0 or negative health - run code!
{
// some code here
}
One more solution is to use array_reduce() to check the condition:
if (array_reduce($_SESSION['player_1_pawn'], function (&$flag, $player) {
$flag &= ($player['currentHealth'] <=0);
return $flag;
}, true));
P.S. Be careful when array $_SESSION['player_1_pawn'] is empty.
I keep getting an error with the following bit of code. It is probably some small thing but I don't see what is wrong.
while($row = mysql_fetch_array($result))
{
$varp = $row['ustk_retail'];
if ($varp<80000) { $o1 = 1; }
if (($varp=>80000) && ($varp<100000)) { $o2 = "1"; }
if (($varp=>100000) && ($varp<120000)) { $o3 = "1"; }
if (($varp=>120000) && ($varp<140000)) { $o4 = "1"; }
if (($varp=>140000) && ($varp<160000)) { $o5 = "1"; }
if (($varp=>160000) && ($varp<180000)) { $o6 = "1"; }
if (($varp=>180000) && ($varp<200000)) { $o7 = "1"; }
if (($varp=>200000) && ($varp<220000)) { $o8 = "1"; }
if (($varp=>220000) && ($varp<240000)) { $o9 = "1"; }
if (($varp=>240000) && ($varp<260000)) { $o10 = "1"; }
if (($varp=>260000) && ($varp<280000)) { $o11 = "1"; }
if (($varp=>280000) && ($varp<300000)) { $o12 = "1"; }
if ($varp>=300000) { $o13 = "1"; }
}
Running php -l (lint) on your code I get a
Parse error: syntax error, unexpected T_DOUBLE_ARROW
The T_DOUBLE_ARROW token is what PHP expects when assigning array values to array keys.
When comparing for Greater than or equal to the PHP Parser expects T_IS_GREATER_OR_EQUAL, meaning you have to use >= instead of =>.
See
the chapter on Comparison Operators in the PHP Manual and
the List of Parser Tokens in the PHP Manual
Greater than or equal to is >= sign, not =>
Update:
You are right. It's small but hard to find mistake.
It took me to split whole line into pieces to see where the problem is:
<?php
if
(
$varp
=>
80000
)
So, it says parse error on line 5 and I had to doublecheck this operator.
Of course, at first I separated the problem line from the rest of the code to be certain.
You have an expression error.
$varp=>220000 // is not a valid php expression
=> operator is used to assign values in arrays like:
$x = array( 'foo' => 'bar');
>= is the comparation assigment greater than or equal
You have made a mistake in the if conditions. The greater than Equal to sign is >= and not =>.
The answer has already been given but thought this was neat enough to share:
PHP accepts boolean expressions in it's switch statement.
switch(TRUE) {
case $range <= 10: echo "range below or equal to 10"; break;
case $range <= 20: echo "range above 10 below or equal to 20"; break;
case $range <= 30: echo "range above 20 below or equal to 30"; break;
default: echo "high range";
}
In my opinion this generates the cleanest most readable code.
This is more readable and compact way to do the same:
$ranges = range(300000, 80000, -20000);
$index = 1;
$varp = 220001;
foreach ($ranges as $i => $range) {
if ($varp >= $range) {
$index = 13 - $i;
break;
}
}
${'o' . $index} = 1;
Anyway - I think you're doing something wrong with using variable name of result.
You probably want to change ($varp=300000) to ($varp==300000) and it might help to enclose the full if-statement inside (), like this
if($varp80000 && $varp100000 && $varp120000 && $varp140000 && $varp160000 && $varp180000 && $varp200000 && $varp220000 && $varp240000 && $varp260000 && $varp280000 && $varp==300000) { $o13 = "1"; }
On another note, where to these strange $varp#### variables come from?
Not sure whether the code you've posted has gotten messed up somehow, but it looks like you're missing "==" in some of the if conditions. Also, as Skilldrick pointed out, the whole if condition should be in parentheses
"Greater than or equal to is >= NOT =>. You use => for arrays for keys/values.
Add one more bracket around the conditions in if....
if ( ($varp80000) && ($varp100000) && ($varp120000) && ($varp140000) && ($varp160000) && ($varp180000) && ($varp200000) && ($varp220000) && ($varp240000) && ($varp260000) && ($varp280000) && ($varp=300000) ) { $o13 = "1"; }