PSR-2 PHP三元运算语法中是否需要括号?

13

问题:PSR-2 PHP三元语法是否需要括号?

我想知道以下两个三元语句哪一个符合PSR-2标准 - 同时我还需要指向文档或权威链接的指引:

$error = ($error_status) ? 'Error' : 'No Error';

或者

$error = $error_status ? 'Error' : 'No Error';


注意:php.net网站上展示了带有括号的语法,但是我没有在任何“官方的PSR-2”文档中找到过这种要求。


结论

如果没有PSR-2标准,哪种方式是最常见的约定?

5个回答

19

PSR-2标准明确省略了任何关于操作符的观点:

本指南有意省略了许多风格和实践要素。包括但不限于:... 操作符和赋值

由于圆括号用于分组表达式,因此您的示例并没有太多意义:

$error = ($error_status) ? 'Error' : 'No Error';

在这里,用括号将单个变量括起来没有意义。在更复杂的情况下,使用括号可能会有所帮助,但在大多数情况下,它们仅用于可读性。

更常见的模式是始终将整个三元表达式括起来:

$error = ($error_status ? 'Error' : 'No Error');

主要动机是因为PHP中的三元运算符具有相当尴尬的结合性和优先级,因此在复杂表达式中使用它通常会产生意外/无用的结果。
一个常见的情况是字符串连接,例如:
$error = 'Status: ' . $error_status ? 'Error' : 'No Error';

在这里,连接运算符(.操作符)实际上是在三元运算符之前被计算的,因此条件总是一个非空字符串(以 'Status: ' 开头),并且您将始终得到字符串 Error' 作为结果。
需要使用括号来防止这种情况发生:
$error = 'Status: ' . ($error_status ? 'Error' : 'No Error');

当我们使用三元表达式来模拟if-elseif语句时,会出现类似的情况。PHP历史上的一个错误导致多个三元运算符从左到右依次计算,而不是在条件为真时跳过整个false分支。

下面是PHP手册中的一个例子,更加清晰地解释了这个问题:

// on first glance, the following appears to output 'true'
echo (true?'true':false?'t':'f');

// however, the actual output of the above is 't'
// this is because ternary expressions are evaluated from left to right

// the following is a more obvious version of the same code as above
 echo ((true ? 'true' : false) ? 't' : 'f');

 // here, you can see that the first expression is evaluated to 'true', which
 // in turn evaluates to (bool)true, thus returning the true branch of the
 // second ternary expression.

2

通常的惯例是保持简洁。PSR标准采用了这种方式。

$error = $error_status ? 'Error' : 'No Error';

看起来比括号更加清晰。

如果你想要更明确的可读性,可以采用PSR-2标准:

if ($error_status) {
    $error = 'Error';
else {
    $error = 'No Error';
}

这是全部内容。PSR是一个标准,用于更好地理解我们的代码,当您像提供的那样编写代码时,您正在深入简化,想象力没有限制,只需避免不符合PSR规则。

使用PHP Code Sniffer检查您的代码是否符合PSR1和PSR2规则。

Code Sniffer


2

需要记住的一件重要事情是,PSR-2规定行不应超过80个字符
三元语法有时可能会非常长,因此我认为我们缺少了一个针对一种非常常见的代码的建议。 目前我所做的是将其缩进如下:

$stuff = $count > MyLongNamespace\MyLongClassName->get('count') 
    ? 'yikes this seems to be some large stuff'
    : 'erm this is rather small stuff';

2
虽然如果您的三元条件语句延伸到这个长度,使用完整的 if () {...} else {...} 块或通过使用“带有可选覆盖”的赋值来跳过 else 可能更易读:$f = 'foo'; if ($case) { $f = 'bar'; }(<-- 在 SO 评论中不要换行。) - beporter

1
如果没有明确规定,那么就没有标准。两者都可以。

如果没有PSR-2标准,哪种方式是最常见的约定? - Tyler Wall
1
惯例倾向于表意清晰。如果第一眼看不清操作顺序,就要加括号。请参考被接受的答案。 - y o

0

对此有一些不同的看法,而且这是一件令人遗憾的任意事情。

从我所见和学到的来看,更常见的情况似乎可以通过以下差异来最好地解释,更具体地说; 括号在任何情况下都不会移动。

长手写法:

if ($is_full_page) {
  echo "medium-6";
} else {
  echo "medium-7";
}

简写:

echo ($is_full_page) ? 'medium-6' : 'medium-7';

对我来说,这就是真正的一致性,美丽无比。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接