75

How do I write a PHP ternary operator with the elseif portion?

I see basic examples with the if and else portions of the PHP ternary operator like this:

echo (true)  ? "yes" : "no";    //prints yes
echo (false) ? "yes" : "no";    //prints no

How do I get the "elseif" portion like this into the ternary operator?

<?php 
  if($result->vocation == 1){
    echo "Sorcerer"; 
  }else if($result->vocation == 2){
    echo 'Druid';
  }else if($result->vocation == 3){
    echo 'Paladin';
  }else if($result->vocation == 4){
    echo 'Knight';
  }else if($result->vocation == 5){
    echo 'Master Sorcerer';
  }else if($result->vocation == 6){
    echo 'Elder Druid';
  }else if($result->vocation == 7){
    echo 'Royal Paladin';
  }else{
    echo 'Elite Knight';
  }
?>
random_user_name
  • 25,694
  • 7
  • 76
  • 115
dynamitem
  • 1,647
  • 6
  • 25
  • 45
  • 4
    You would be better off using a switch, or even better, an array lookup map. A ternary by definition is if-then-else. Writing a ternary to try and do what you want would be very difficult to read / follow. – random_user_name Jul 31 '13 at 22:02
  • @cale_b Could you clarify it a bit? I'm still learning PHP and in my work I've only used if-elseif-else statements, so I'm not so familiar with all these things. – dynamitem Jul 31 '13 at 22:04
  • I gave an example below. If you're not going to use a database, then this solution is clean and easy to understand. – random_user_name Jul 31 '13 at 22:05

10 Answers10

127

A Ternary is not a good solution for what you want. It will not be readable in your code, and there are much better solutions available.

Why not use an array lookup "map" or "dictionary", like so:

$vocations = array(
    1 => "Sorcerer",
    2 => "Druid",
    3 => "Paladin",
    ...
);

echo $vocations[$result->vocation];

A ternary for this application would end up looking like this:

echo($result->group_id == 1 ? "Player" : ($result->group_id == 2 ? "Gamemaster" : ($result->group_id == 3 ? "God" : "unknown")));

Why is this bad? Because - as a single long line, you would get no valid debugging information if something were to go wrong here, the length makes it difficult to read, plus the nesting of the multiple ternaries just feels odd.

A Standard Ternary is simple, easy to read, and would look like this:

$value = ($condition) ? 'Truthy Value' : 'Falsey Value';

or

echo ($some_condition) ? 'The condition is true!' : 'The condition is false.';

A ternary is really just a convenient / shorter way to write a simple if else statement. The above sample ternary is the same as:

if ($some_condition) {
    echo 'The condition is true!';
} else {
    echo 'The condition is false!';
}

However, a ternary for a complex logic quickly becomes unreadable, and is no longer worth the brevity.

echo($result->group_id == 1 ? "Player" : ($result->group_id == 2 ? "Gamemaster" : ($result->group_id == 3 ? "God" : "unknown")));

Even with some attentive formatting to spread it over multiple lines, it's not very clear:

echo($result->group_id == 1 
    ? "Player" 
    : ($result->group_id == 2 
        ? "Gamemaster" 
        : ($result->group_id == 3 
            ? "God" 
            : "unknown")));
random_user_name
  • 25,694
  • 7
  • 76
  • 115
  • Instead of doing this `$qvar = isset($_GET['qvar']) ? $_GET['qvar'] : 'default';` we can do this `$qvar = $_GET['qvar'] ?? 'default';` I am not sure which PHP version was this introduced in? – AhmadKarim Jul 12 '20 at 15:23
  • @AhmadKarim this is called the [null coalescing operator (??)](https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op) and was introduced in PHP 7. – compuphys Feb 04 '21 at 09:36
12

Since this would be a common task I would suggest wrapping a switch/case inside of a function call.

function getVocationName($vocation){
    switch($vocation){
        case 1: return "Sorcerer";
        case 2: return 'Druid';
        case 3: return 'Paladin';
        case 4: return 'Knight';
        case 5: return 'Master Sorcerer';
        case 6: return 'Elder Druid';
        case 7: return 'Royal Paladin';
        default: return 'Elite Knight';
    }
}

echo getVocationName($result->vocation);
Orangepill
  • 24,500
  • 3
  • 42
  • 63
8
echo ($result ->vocation == 1) ? 'Sorcerer'
        : ($result->vocation == 2) ? 'Druid'
           :  ($result->vocation == 3) ? 'Paladin'
                    ....

;

It’s kind of ugly. You should stick with normal if statements.

TRiG
  • 10,148
  • 7
  • 57
  • 107
thelolcat
  • 10,995
  • 21
  • 60
  • 102
7

How to write a basic PHP Ternary Operator:

($your_boolean) ? 'This is returned if true' : 'This is returned if false';

Example:

$myboolean = true;
echo ($myboolean) ? 'foobar' : "penguin";
foobar

echo (!$myboolean) ? 'foobar' : "penguin";
penguin

A PHP ternary operator with an 'elseif' crammed in there:

$chow = 3;
echo ($chow == 1) ? "one" : ($chow == 2) ? "two" : "three";
three

But please don't nest ternary operators except for parlor tricks. It's a bad code smell.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
5

I'd rather than ternary if-statements go with a switch-case. For example:

switch($result->vocation){
case 1:
    echo "Sorcerer";
    break;
case 2:
    echo "Druid";
    break;
case 3:
    echo "Paladin";
    break;
case 4:
    echo "Knight";
    break;
case 5:
    echo "Master Sorcerer";
    break;
case 6:
    echo "Elder Druid";
    break;
case 7:
    echo "Royal Paladin";
    break;
default:
    echo "Elite Knight";
    break;
}
madsroskar
  • 1,138
  • 13
  • 26
4

You wouldn’t: it’s messy and hard to read.

You’re looking for the switch statement in the first case. The second is fine as it is but still could be converted for consistency

Ternary statements are much more suited to boolean values and alternating logic.

TRiG
  • 10,148
  • 7
  • 57
  • 107
exussum
  • 18,275
  • 8
  • 32
  • 65
3

To be honest, a ternary operator would only make this worse, what i would suggest if making it simpler is what you are aiming at is:

$groups = array(1=>"Player", 2=>"Gamemaster", 3=>"God");
echo($groups[$result->group_id]);

and then a similar one for your vocations

$vocations = array(
  1=>"Sorcerer",
  2=>"Druid",
  3=>"Paladin",
  4=>"Knight",
  ....
);
echo($vocations[$result->vocation]);

With a ternary operator, you would end up with

echo($result->group_id == 1 ? "Player" : ($result->group_id == 2 ? "Gamemaster" : ($result->group_id == 3 ? "God" : "unknown")));

Which as you can tell, only gets more complicated the more you add to it

bizzehdee
  • 20,289
  • 11
  • 46
  • 76
3

In addition to all the other answers, you could use switch. But it does seem a bit long.

switch ($result->vocation) {
case 1:
    echo 'Sorcerer';
    break;

case 2:
    echo 'Druid';
    break;

case 3:
    echo 'Paladin';
    break;

case 4:
    echo 'Knight';
    break;

case 5:
    echo 'Master Sorcerer';
    break;

case 6:
    echo 'Elder Druid';
    break;

case 7:
    echo 'Royal Paladin';
    break;

default:
    echo 'Elite Knight';
    break;
}
federico-t
  • 12,014
  • 19
  • 67
  • 111
3

You could also do:

echo "yes" ?: "no" // Assuming that yes is a variable that can be false.

Instead of:

echo (true)  ? "yes" : "no";
3

PHP 8 (Left-associative ternary operator change)

Left-associative ternary operator deprecation https://wiki.php.net/rfc/ternary_associativity. The ternary operator has some weird quirks in PHP. This RFC adds a deprecation warning for nested ternary statements. In PHP 8, this deprecation will be converted to a compile time error.

1 ? 2 : 3 ? 4 : 5;   // deprecated
(1 ? 2 : 3) ? 4 : 5; // ok

source: https://stitcher.io/blog/new-in-php-74#numeric-literal-separator-rfc

DevWL
  • 17,345
  • 6
  • 90
  • 86