Укладка нескольких тернарных операторов в PHP

Вот что я написал:

$Myprovince = ( ($province == 6) ? "city-1" : ($province == 7) ? "city-2" : ($province == 8) ? "city-3" : ($province == 30) ? "city-4" : "out of borders" ); 

Но для каждого поля я получил значение city-4 . Я хочу использовать тройные операторы вместо switch/if потому что я хочу поэкспериментировать и посмотреть, как это будет сделано.

В чем проблема с этим кодом?

    Другие уже предложили правильный способ сделать это, но если вы действительно хотите использовать тернарный оператор, вам нужно использовать скобки как:

     $province = 7; $Myprovince = ( ($province == 6) ? "city-1" : (($province == 7) ? "city-2" : (($province == 8) ? "city-3" : (($province == 30) ? "city-4" : "out of borders"))) ); 

    Смотрите на идеон

    Тернарный оператор оценивается слева направо. Поэтому, если вы не группируете выражения правильно, вы получите неожиданный результат.

    Совет PHP [docs] :

    Рекомендуется избегать «укладки» тернарных выражений. Поведение PHP при использовании нескольких трёхмерных операторов в одном выражении неочевидно.

    Ваш код фактически оценивается как:

     ( ( ( $province == 6 ? "city-1" : $province == 7 ) ? "city-2" : $province == 8 ) ? "city-3" : $province == 30 ) ? "city-4" : "out of borders"; 

    где это должно быть

     $province == 6 ? "city-1" : ( $province == 7 ? "city-2" : ( $province == 8 ? "city-3" : ( $province == 30 ? "city-4" : "out of borders" ) ) ); 

    Этот код может выглядеть отлично, но кто-то его прочитает, и им потребуется больше времени, чем нужно, чтобы понять, что делает этот код.


    Вам было бы лучше с чем-то вроде этого:

     $map = array( 6 = >'city-1', 7 => 'city-2', 8 => 'city-3', 30 => 'city-4'); $Myprovince = "out of borders"; if(array_key_exists($province, $map)) { $Myprovince = $map[$province]; } 

    Или как @Jonah упомянул в своем комментарии:

     $Myprovince = isset($map[$province]) ? $map[$province] : 'out of borders'; 

    Не злоупотребляйте тернарным оператором для такого рода вещей. Это делает отладки почти невозможным. Почему бы не сделать что-то вроде

     switch($province) { case 6: $Myprovince = "city-1"; break; case 7: ... } 

    или просто прикованный, если / then / else

     if ($province == 6) { $Myprovince = "city-1"; } elseif ($province = ...) { ... } 

    Некоторые люди предложили использовать оператор switch или оператор if / else. Но вместо этого я бы использовал массив, чтобы упростить его и упростить для чтения:

     $provinces = array ( 6 => 'city-1', 7 => 'city-2', 8 => 'city-3', 30 => 'city-4' ); // then you can call: $Myprovince = isset($provinces[$province]) ? $provinces[$province] : 'out of borders'; 

    Зачем?

    В конце концов, код будет легче управлять. Может быть, вам захочется добавить эти сопоставления между городами из базы данных в один прекрасный день .. и т. Д. Это будет сложно поддерживать с кучей операторов switch / case.

    Попробуйте еще скобки:

     $Myprovince = ( ($province == 6) ? "city-1" : (($province == 7) ? "city-2" : (($province == 8) ? "city-3" : (($province == 30) ? "city-4" : "out of borders" )))); 

    У вашего кода есть проблема с приоритетом троичного оператора.

    Но я думаю, что вы действительно должны отказаться от этого оператора и попытаться использовать switch .

    Я понимаю, что это вопрос о PHP, но поскольку это всего лишь учебное упражнение, я думал, что вам может быть интересно узнать, что Ruby и Javascript действительно ведут себя так, как вы ожидаете.

    Рубин:

     ree-1.8.7-2012.02 :009 > def foo x ree-1.8.7-2012.02 :010?> x == 1 ? "city 1" : x == 2 ? "city 2" : "out of borders" ree-1.8.7-2012.02 :011?> end => nil ree-1.8.7-2012.02 :012 > foo 1 => "city 1" ree-1.8.7-2012.02 :013 > foo 2 => "city 2" ree-1.8.7-2012.02 :014 > foo 3 => "out of borders" 

    Javascript:

     > function f(x) { return x == 1 ? "city 1" : x == 2 ? "city 2" : "out of borders"; } undefined > f(1) "city 1" > f(2) "city 2" > f(3) "out of borders" 

    Вместо этого используйте переключатель. Тернарные операторы действительно не должны использоваться для более чем одного условия, так как они быстро становятся очень трудными для понимания.

     switch ($province) { case 6: $Myprovince = 'city-1'; break; case 7: $Myprovince = 'city-2'; break; case 8: $Myprovince = 'city-3'; break; case 30: $Myprovince = 'city-4'; break; default: $Myprovince = 'out of borders'; }