2

来自 C# 我必须用 PHP 做一个项目。

我正在使用这段代码:

$transport = 'T';

$vehicle = (
 ( $transport == 'B' ) ? 'bus' :
 ( $transport == 'A' ) ? 'airplane' :
 ( $transport == 'T' ) ? 'train' :
 ( $transport == 'C' ) ? 'car' :
 ( $transport == 'H' ) ? 'horse' :
 'feet' );

echo $vehicle;

我希望它能够打印train,但我得到了horse。键盘示例:http ://codepad.org/rWllfrht

谁能解释这种奇怪的行为?

4

6 回答 6

16

在其他答案中没有看到任何关于为什么您的代码被破坏的解释,所以这里有一个快速的总结。

这里的问题更明显的是你添加了括号以使评估的隐含顺序更加明确。

这是您的代码的精简版本,它仍然会产生“马”的错误结果:

 $t = 'T';

 ( $t == 'T' ) ? 'train' : 
 ( $t == 'C' ) ? 'car' : 
 ( $t == 'H' ) ? 'horse' : 'feet';

首先,让我们展开它:

( $t == 'T' ) ? 'train' : ( $t == 'C' ) ? 'car' : ( $t == 'H' ) ? 'horse' : 'feet'; 

接下来,我将在已经存在隐式括号的地方添加显式括号:

((($t == 'T') ? 'train' : ($t == 'C')) ? 'car' : ($t == 'H')) ? 'horse' : 'feet';

接下来,我们可以解决您的比较:

((true ? 'train' : false) ? 'car' : false) ? 'horse' : 'feet';

您应该开始了解为什么会出现这种情况。第一个三元计算true ? 'train' : 'false''train'

('train' ? 'car' : false) ? 'horse' : 'feet';

因为'train'当转换为布尔值时为真,所以现在的结果是'car'

'car' ? 'horse' : 'feet';

同样,因为非空字符串是“真”,所以结果现在是“马”。因此,当 a 第一次true出现在你可怕的嵌套 case 语句中时,结果将级联所有剩余的语句,为下一个运算符的“true”分支抛出先前的值。

解决方案是避免使用此代码。这是一种过于聪明的尝试,结果是一个破碎的、难以理解的混乱。绝对没有理由使用它。选择一个switch声明,它是为您想要做的事情而设计的。

于 2012-10-30T15:53:06.650 回答
3

由于 PHP 语言语法中的错误,这不能按预期工作,如下所示:http ://en.wikipedia.org/wiki/%3F:#PHP

这是一个可以工作的简单版本:

$transport = 'T';

$vehicle = (
 ( $transport == 'B' ? 'bus' :
 ( $transport == 'A' ? 'airplane' :
 ( $transport == 'T'  ? 'train' :
 ( $transport == 'C'  ? 'car' :
 ( $transport == 'H'  ? 'horse' :
 'feet' ))))));

echo $vehicle;

但正如其他人所说,我同意这不是最好的方法。您可以使用 switch case、if else if 或关联数组,并且更具可读性。

于 2012-10-30T15:49:28.340 回答
1

这是 PHP 的一种“按预期工作,即使它显然是错误的”行为。它不会以这种方式关联,因此虽然此代码适用于大多数其他语言,但它会在 PHP 中失败。课?学会在不寻常的关联范式上使用括号。第二课?三元不是灵丹妙药,虽然它既美观又紧凑,但只能在可读时使用。恕我直言,嵌套的三元语句很丑陋。

于 2012-10-30T15:48:45.673 回答
0

我不确定您为什么选择使用这种形式的语法,正如评论中提到的那样,这将是调试的噩梦……开关盒在这里可能是更好的选择-

$vehicle = '';
switch($transport){
  case 'B' :
    $vehicle = 'bus';
  break;
  case 'A' :
    $vehicle = 'airplane';
  break;
  ...
  default:
   // undefined cases
  break;
}

参考 -

于 2012-10-30T15:40:24.270 回答
0

如果您想做这样的事情,请学会爱上括号:

$vehicle =     ( ( $transport == 'B' ) ? 'bus' : 
                    (( $transport == 'A' ) ? 'airplane' :
                       (( $transport == 'T' ) ? 'train' :
                         (( $transport == 'C' ) ? 'car' :
                           (( $transport == 'H' ) ? 'horse' :'feet')))) );

由于 PHP 对三元的操作顺序http://php.net/manual/en/language.operators.comparison.php,需要清楚地包含三元的每个右侧。

顺便说一句,从那个页面他们明确建议不要像这样堆叠它们......

注意:建议您避免“堆叠”三元表达式。在单个语句中使用多个三元运算符时 PHP 的行为并不明显:

于 2012-10-30T15:42:22.427 回答
-1

我不建议您使用此类代码,但出于教育目的,它应该是

$transport = 'T';
$vehicle = (
        ($transport == 'B') ? 'bus' : 
            (($transport == 'A') ? 'airplane' : 
                (($transport == 'T') ? 'train' : 
                        (($transport == 'C') ? 'car' : 
                                (($transport == 'H') ? 'horse' : 'feet'))))
        );

echo $vehicle;

更好的代码应该是

$transport = 'T';
switch ($transport) {
    case 'A' :
        $vehicle = 'airplane';
        break;
    case 'B' :
        $vehicle = 'bus';
        break;
    case 'C' :
        $vehicle = 'car';
        break;
    case 'H' :
        $vehicle = 'horse';
        break;
    case 'T' :
        $vehicle = 'train';
        break;
    default :
        $vehicle = 'teleportation';
        break;
}

echo $vehicle;

或者更好:

$transport = 'T';
$array = array('A'=>'airplane','B'=>"bus","C"=>"car","H"=>"horse","T"=>"train");
echo isset($array[$transport]) ? $array[$transport] : null;

或者,使用数据库:

 SELECT name FROM transpotationTable WHERE someKey = '$transport' 
于 2012-10-30T15:48:37.883 回答