7
\$\begingroup\$
if($row['best']){
 $id = $row['best'];
} elseif($row['average']){
 $id = $row['average'];
} elseif($row['bad']){
 $id = $row['bad'];
} 

If row['best'] is null, I need $id to equal the 2nd best. If 2nd best is null, $id is equal to the next best.

syb0rg
21.9k10 gold badges113 silver badges192 bronze badges
asked Mar 31, 2014 at 17:00
\$\endgroup\$
1
  • 10
    \$\begingroup\$ Can you add a bit of the surrounding context to your question? Where does the $row variable come from? I can imagine that there might be a possible solution where the problem can be fixed elsewhere in your code. \$\endgroup\$ Commented Mar 31, 2014 at 17:10

6 Answers 6

10
\$\begingroup\$

Simon has already answered while I was writing something similar:

foreach(array('best', 'average', 'bad') as $rank) {
 if($row[$rank]) {
 $id = $row[$rank];
 break;
 }
}

Note however, that in both this and Simon's answer, there is a possibility of $id never being assigned a value. Konijn's answer avoids that (although $id might still end up false'y)

answered Mar 31, 2014 at 17:15
\$\endgroup\$
2
  • \$\begingroup\$ Just assign $id the desired no-match value before the loop. \$\endgroup\$ Commented Apr 4, 2014 at 2:03
  • \$\begingroup\$ @DavidHarkness Oh sure, it's easy to handle. Just wanted to keep the code 1:1 with OP's question \$\endgroup\$ Commented Apr 4, 2014 at 8:18
10
\$\begingroup\$

How has no one mentioned the Elvis operator?!

$id = $row['best'] ?: $row['average'] ?: $row['bad'] ?: null;

Substitute your desired "not present" value of choice for null.

Edit: This is the short form of the ternary operator which evaluates to the first expression if truthy or the second expression if not. This is similar to how the || operator is often used in JavaScript.

var options = options || {};
answered Apr 1, 2014 at 1:37
\$\endgroup\$
3
  • \$\begingroup\$ "Elvis operator"? Never seen that one before, seems to be some ternary-operator-magic there. \$\endgroup\$ Commented Apr 2, 2014 at 11:15
  • 1
    \$\begingroup\$ Careful. If $row[xxx] doesn't exist you'll get nasty error notices. \$\endgroup\$ Commented Apr 2, 2014 at 21:42
  • \$\begingroup\$ @mAsT3RpEE Correct, same for all of the code on this page. \$\endgroup\$ Commented Apr 3, 2014 at 8:38
5
\$\begingroup\$

You may want to write the first_in($arr, $keys) function, and rewrite your code as:

$id = first_in($row, array('best', 'average', 'bad'));

Or more common firstof($arr) function:

$id = firstof(array($row['best'], $row['average'], $row['bad'));

for example, the firstof function:

function firstof($arr) {
 foreach ($arr as $key=>$val)
 if ($val)
 return $val;
 return $arr[count($arr)-1];
}
answered Apr 1, 2014 at 0:18
\$\endgroup\$
4
\$\begingroup\$

From here:

If there are only 3 possibilities, you could do this:

$id = $row['best'] or $id = $row['average'] or $id = $row['bad'];

This is the closest that PHP can come to JS short circuit assignments.

answered Mar 31, 2014 at 17:13
\$\endgroup\$
3
  • \$\begingroup\$ I have up to 8 possibilities. For readability, I would rather use if-then-else. No? \$\endgroup\$ Commented Mar 31, 2014 at 17:41
  • \$\begingroup\$ Actually, this could still work with 8, but you would need some newlines, or, you could use @Flambino's approach which is still better than if-then-else \$\endgroup\$ Commented Mar 31, 2014 at 17:44
  • \$\begingroup\$ @Bastien Oh, with 8 possibilities I would definitely use one of the iteration methods. You should update your question to reflect this requirement. Programmers tend to be literal creatures at heart. :) \$\endgroup\$ Commented Apr 4, 2014 at 1:59
4
\$\begingroup\$

There are some different approaches possible here, one of them is to use an array:

$arr = array($row['best'], $row['average'], $row['bad']);
for ($arr as $value) {
 if ($value) {
 $id = $value;
 break;
 }
}

If you consider this as a better way or not to do what you are trying to accomplish, is really up to you. I can imagine that if the possible options will be extended, then this would be really helpful. But for only three items, your current way is not that bad.

palacsint
30.3k9 gold badges82 silver badges157 bronze badges
answered Mar 31, 2014 at 17:09
\$\endgroup\$
2
\$\begingroup\$

Maybe use array functions a bit?

$keys = array_keys($row, TRUE); // returns all keys for which value is boolean TRUE
$id = $keys[0]; // takes first one as ID

Note that this assume only one of the values is set to true or that keys are ordered from the one you want to get the most to one you want the least. It's often a safe assumption, but assumption none the less. Thus, my code is not an universal replacement of your original code, but in many real-life situations it would be pretty good - and it frees you from duplicating lists of possible keys in different parts of the script.

answered Apr 1, 2014 at 11:42
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.