Понимание вложенного PHP тернарного оператора - PullRequest
16 голосов
/ 03 июня 2011

Я не понимаю, как получается этот вывод ("four")?

$a = 2;

echo
  $a == 1 ? 'one'   :
  $a == 2 ? 'two'   :
  $a == 3 ? 'three' :
  $a == 5 ? 'four'  : 
    'other'  
  ;

// prints 'four'

Я не понимаю, почему печатается "four".

Ответы [ 4 ]

26 голосов
/ 03 июня 2011

Вам нужно заключить в скобки троичные условия:

<?php

for ($a=0; $a < 7; $a++) {
  echo (
    $a == 1 ? 'one' :
    ($a == 2 ? 'two' :
    ($a == 3 ? 'three' :
    ($a == 5 ? 'four' : 'other'))));
    echo "\n";
    // prints 'four'
}
exit;
?>

возвращается:

other
one
two
three
other
four
other

как и следовало ожидать.

См. Примечание внизу «Тернарные операторы» в PHP Справка по троичным операторам .

Выражения оцениваются слева направо. Итак, вы на самом деле получаете:

  echo (
    ((($a == 1 ? 'one' : $a == 2)
     ? 'two' : $a == 3) ? 'three' :
    $a == 5) ? 'four' : 'other');

Итак, для $a=2 вы получите:

  echo (
    ((($a==2) ? 'two' : $a == 3) ? 'three' :
    $a == 5) ? 'four' : 'other');

, а затем

  echo (
    ((true ? 'two' : $a == 3) ? 'three' :
    $a == 5) ? 'four' : 'other');

, а затем

  echo (
    ('two' ? 'three' : $a == 5) ? 'four' : 'other');

, а затем

  echo (
    'three' ? 'four' : 'other');

и так echo 'four'.

Помните, что PHP динамически типизирован и обрабатывает любые ненулевые ненулевые значения как ИСТИНА.

6 голосов
/ 03 июня 2011

Вкл. Страница операторов сравнения в руководстве по PHP объясняет, что поведение PHP "неочевидно" при вложении ( укладка) троичные операторы.

Код, который вы написали, выглядит так:

$a = 2;

echo
  ((($a == 1  ? 'one'   :
     $a == 2) ? 'two'   :
     $a == 3) ? 'three' :
     $a == 5) ? 'four'  : 
       'other'
  ;

// prints 'four'

Поскольку $a равно 2, а 'two' и 'three' также ИСТИНА, в результате вы получите «four», так как вы больше не сравниваете, если 'four' ИСТИНА или нет .

Если вы хотите изменить это, вы должны поставить скобки в разных местах [также отмечено: BeingSimpler и MGwynne]:

$a = 2;
echo 
  ($a == 1 ? 'one'   :
  ($a == 2 ? 'two'   :
  ($a == 3 ? 'three' :
  ($a == 5 ? 'four'  : 
     'other'))))
  ;

// prints 'two'
3 голосов
/ 03 июня 2011

Проблема с условиями группировки, просто нужно добавить скобки для их разделения.

$a = 2;
echo (
$a == 1 ? 'one' :
($a == 2 ? 'two' :
($a == 3 ? 'three' :
($a == 5 ? 'four' : 'other'))));
echo "\n";
// prints 'four'
exit;

Решено.

1 голос
/ 13 января 2018

Это то, что я придумал, чтобы помочь себе понять левую и правую ассоциативность для троичного оператора.

// PHP

$a = "T";
$vehicle =  $a == "B" ? "bus" :
            $a == "A" ? "airplane" :
            $a == "T" ? "train" :
            $a == "C" ? "car" :
            $a == "H" ? "horse" : "feet";

            // (as seen by the PHP interpreter)
            // INITIAL EXPRESSION: ((((($a == "B" ? "bus" : $a == "A") ? "airplane" : $a == "T") ? "train" : $a == "C") ? "car" : $a == "H") ? "horse" : "feet");
            // STEP 1:             (((((FALSE ? "bus" : FALSE) ? "airplane" : TRUE) ? "train" : FALSE) ? "car" : FALSE) ? "horse" : "feet")
            // STEP 2:             ((((FALSE ? "airplane" : TRUE) ? "train" : FALSE) ? "car" : FALSE) ? "horse" : "feet")
            // STEP 3:             (((TRUE ? "train" : FALSE) ? "car" : FALSE) ? "horse" : "feet")
            // STEP 4:             (("train" ? "car" : FALSE) ? "horse" : "feet")
            // STEP 5:             ("car" ? "horse" : "feet")
            // FINAL EVALUATION:   ("horse")

            // If you used the initial expression here (with the parenthesis) in a different language, it would also evaluate to "horse."

echo $vehicle; // gives us "horse"

Это противоположно:

// EVERY OTHER LANGUAGE

var a = "T";
var vehicle =   a == "B" ? "bus" :
                a == "A" ? "airplane" :
                a == "T" ? "train" :
                a == "C" ? "car" :
                a == "H" ? "horse" : "feet";

                // (as seen by the other language's interpreter)
                // INITIAL EXPRESSION: (a == "B" ? "bus" : (a == "A" ? "airplane" : (a == "T" ? "train" : (a == "C" ? "car" : (a == "H" ? "horse" : "feet")))));
                // STEP 1:             (FALSE ? "bus" : (FALSE ? "airplane" : (TRUE ? "train" : (FALSE ? "car" : (FALSE ? "horse" : "feet")))))
                // STEP 2:             (FALSE ? "bus" : (FALSE ? "airplane" : (TRUE ? "train" : (FALSE ? "car" : "feet"))))
                // STEP 3:             (FALSE ? "bus" : (FALSE ? "airplane" : (TRUE ? "train" : "feet")))
                // STEP 4:             (FALSE ? "bus" : (FALSE ? "airplane" : "train"))
                // STEP 5:             (FALSE ? "bus" : "train")
                // FINAL EVALUATION:   ("train")

                // If you used the initial expression here (with the parenthesis) in PHP, it would also evaluate to "train."

console.log(vehicle); // gives us "train"

Если выОбратите внимание, что в примере PHP самое внутреннее выражение находится слева, а во втором примере самое внутреннее выражение справа.Каждый шаг оценивает следующее самое внутреннее выражение, пока не будет единственного результата.Скобки очень важны, если вы собираетесь вкладывать троичные операции в PHP!

...