php 长 if 条件的 PSR-2 标准

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23758916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 16:55:08  来源:igfitidea点击:

PSR-2 standard for long if-conditions

phpconvention

提问by user3631654

I did not find any standard for this case:

我没有找到这种情况的任何标准:

if ($a == $b && $b == $c && $c == $d && $g == $d) {

}

or

或者

if (($a == $b && $b == $c) && ($c == $d && $g == $d)) {

}

Imagine the var-names are longer and 80 letters are exceeded. How should I handle this? It could look like:

想象一下 var-name 更长并且超过了 80 个字母。我该如何处理?它可能看起来像:

if (
       $a == $b
    && $b == $c
    && $c == $d
    && $g == $d
) {

    }

回答by Nic Wortel

There is no recommendation / convention for this case, and as Halcyon already mentioned this is a quite exceptional case.

没有针对这种情况的建议/约定,正如 Halcyon 已经提到的,这是一个非常特殊的情况。

However, there is a recommendation for a function call with a long list of parameters:

但是,建议使用带有一长串参数的函数调用:

Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.

参数列表可以分成多行,其中每个后续行缩进一次。这样做时,列表中的第一项必须在下一行,并且每行必须只有一个参数。

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

So if I had to create an if-statement similar to your's, I'd do this:

因此,如果我必须创建一个类似于您的 if 语句,我会这样做:

if (
    $a == $b &&
    $b == $c &&
    $c == $d &&
    $g == $d
) {
    // do something
}

As you can see, this is almost the same as the solution you proposed yourself, but I prefer adding the &&operators after the conditions.

如您所见,这与您自己提出的解决方案几乎相同,但我更喜欢&&在条件后添加运算符。

回答by Maurice

Personally, I prefer

就个人而言,我更喜欢

if ($a == $b
    && $b == $c
    && $c == $d
    && $g == $d
) {
    // code here...
}

For each line, you start with the double ampersand, indicating that the following statement is separate from the others. If you put the ampersand on the end of the line, it can become less obvious when the lines vary a lot in length.

对于每一行,您都以双与号开头,表示以下语句与其他语句是分开的。如果您将与号放在行尾,当行的长度变化很大时,它会变得不那么明显。

For example;

例如;

if ($a == $b && 
    $b == $c && 
    $thisisamuchlongerstatementbecauseofthisvar == $d && 
    $g == $d
) {
    // code here...
}

In this case you have to scan the code more to know that each line is connected by a double ampersand.

在这种情况下,您必须更多地扫描代码才能知道每条线都由双与号连接。

回答by tleb

Edit

编辑

One year later, I would strongly recommend to rewrite your code to have a shorter if statement. Through variables or function calls.

一年后,我强烈建议重写您的代码以使用更短的 if 语句。通过变量或函数调用。

Original

原来的

I came into this situation, so I decided to go with the following format:

我遇到了这种情况,所以我决定采用以下格式:

if (
    $a == $b &&
    $b == $c &&
    $c == $d &&
    $g == $d) {
}

But, I use phpcbf, which transformed (following the PSR2 standard) the previous code into:

但是,我使用 phpcbf,它将(遵循 PSR2 标准)之前的代码转换为:

if ($a == $b &&
    $b == $c &&
    $c == $d &&
    $g == $d) {
}

I wanted to know more: how does it know that this is the behaviour expected by the standard if it is not written anywhere? Well, the answer is simple: the case is taken into account by the standard, by the following sentence:

我想知道更多:如果没有写在任何地方,它怎么知道这是标准所期望的行为?嗯,答案很简单:标准将案例考虑在内,通过以下句子:

There MUST NOT be a space after the opening parenthesis

左括号后不能有空格

This explains why the second snippet is the one, and the only one, which follows the PSR-2 standard, as declared by php-fig.

这解释了为什么第二个片段是唯一一个遵循 PSR-2 标准的片段,正如php-fig所声明的那样。

回答by inwerpsel

I prefer putting logical operators in long if statements at the beginning of the line, mainly for readability and better behavior in version control.

我更喜欢将逻辑运算符放在行首的长 if 语句中,主要是为了可读性和更好的版本控制行为。

Note that as also mentioned in the other answers it's usually a code smell to have long if statements. However sometimes you have to do it, or the code is already there and you can't rewrite it, so if it's already a bad thing then it helps not to make even more of a mess.

请注意,正如其他答案中所提到的,如果语句很长,通常是一种代码味道。然而有时你必须这样做,或者代码已经存在并且你无法重写它,所以如果它已经是一件坏事,那么它有助于避免变得更加混乱。

Also these things apply to if statements with just a single "and" where the different elements are so long you still need to split it to multiple lines (long variable or class names for instance).

这些事情也适用于只有一个“和”的 if 语句,其中不同的元素很长,您仍然需要将其拆分为多行(例如长变量或类名)。

if (
    $something->getValue() === 'some_value'
    || (
        $something instanceof SomeClass
        && $something->has($someNumber)
        && $someNumber > 42
    )
) {
    // do something
}

Readability: As all logical operators are vertically grouped you can instantly see which operator is on each line. As your eye scans the code it can just move straight vertically and it only needs to move horizontally when there is an actual extra logical level.

可读性:由于所有逻辑运算符都是垂直分组的,因此您可以立即看到每行上的运算符。当您的眼睛扫描代码时,它可以直接垂直移动,并且只有在实际存在额外的逻辑级别时才需要水平移动。

If the operators are at the end of the line your eye needs to move back and forth randomly between lines of uneven lenght.

如果操作员在线路的末端,您的眼睛需要在长度不均匀的线路之间随机来回移动。

Better behavior in version control: When an extra clause is added at the bottom of the if statement then this translates to 1 line added and 0 removed in version control.

版本控制中的更好行为:当在 if 语句底部添加额外的子句时,这将转换为在版本控制中添加 1 行和删除 0 行。

diff --git a/3.php b/3.php
index 367c57c..2a40c3a 100644
--- a/3.php
+++ b/3.php
@@ -6,6 +6,7 @@ 
    if (
         $something instanceof SomeClass
         && $something->has($someNumber)
         && $someNumber > 42
+        && $anotherCase
    ) {
     // do something

If you put logical operators at the end then that will be 2 lines added and 1 removed. That in turn obscures useful information: your commit message for the last change will be shown for both lines when you Git annotate, so you would have to go to the previous version to see the commit message for the line you added the operator to.

如果将逻辑运算符放在最后,则将添加 2 行并删除 1 行。这反过来又掩盖了有用的信息:当您进行 Git 注释时,两行都将显示上次更改的提交消息,因此您必须转到之前的版本才能查看添加了运算符的行的提交消息。

diff --git a/4.php b/4.php
index f654780..2b9e0c5 100644
--- a/4.php
+++ b/4.php
@@ -5,7 +5,8 @@ 
    if (
        $something instanceof SomeClass &&
        $something->has($someNumber) &&
-       $someNumber > 42
+       $someNumber > 42 &&
+       $anotherCase
     ) {
     // do something

回答by Ernesto Allely

Worth mention that the new standard PSR-12, that replaces PSR-2, clarifies this question.

值得一提的是,取代 PSR-2的新标准PSR-12澄清了这个问题。

Expressions in parentheses MAY be split across multiple lines, where each subsequent line is indented at least once. When doing so, the first condition MUST be on the next line. The closing parenthesis and opening brace MUST be placed together on their own line with one space between them. Boolean operators between conditions MUST always be at the beginning or at the end of the line, not a mix of both.

括号中的表达式可以分成多行,其中每一行至少缩进一次。这样做时,第一个条件必须在下一行。右括号和左大括号必须放在它们自己的一行上,它们之间有一个空格。条件之间的布尔运算符必须始终位于行首或行尾,而不是两者的混合。

<?php

if (
    $expr1
    && $expr2
) {
    // if body
} elseif (
    $expr3
    && $expr4
) {
    // elseif body
}

Source: https://www.php-fig.org/psr/psr-12/#51-if-elseif-else

来源:https: //www.php-fig.org/psr/psr-12/#51-if-elseif-else

回答by Nicolas

My favourite approach is to remove sub-expressions from the IF statement, as follows:

我最喜欢的方法是从 IF 语句中删除子表达式,如下所示:

$c1 = $a == $b;
$c2 = $b == $c;
$c3 = $c == $d;
$c4 = $g == $d;
if ($c1 && $c2 && $c3 && $c4) {
}

This approach will make it also easier to debug.

这种方法也将使调试更容易。

The second case you expose is equivalent to the first one due to the associative property of the logic operators. Therefore, $a && $b && $cis the same as ($a && $b) && $c, which is the same as $a && ($b && $c)

由于逻辑运算符关联属性,您公开的第二种情况与第一种情况相同。因此,$a && $b && $c与 相同($a && $b) && $c,与$a && ($b && $c)

回答by tol

I prefer it at the beginning as well:

我也更喜欢一开始的:

if (   self::LOG_ALL
    || (    self::DEBUG__EXECUTION_TIME__IS_ENABLED
        && (self::DEBUG__EXECUTION_TIME__THRESHOLD_SECONDS < $trxDurinationSeconds)
       )
) {
    doSomething();
}

回答by deceze

I would suggest you try to think about the operation in different terms. For example:

我建议您尝试从不同的角度考虑操作。例如:

if (count(array_unique([$a, $b, $c, $d, $g])) == 1)

You will perhaps find that you can express the whole algorithm as more of an operation on a set, use an array instead of individual variables and use logical operations on the set like shown above. That can lead to drastically different and more readable code.

您可能会发现,您可以将整个算法表达为对集合的更多操作,使用数组而不是单个变量,并对集合使用逻辑运算,如上所示。这可能会导致截然不同且更具可读性的代码。

Another example of refactoring:

重构的另一个例子:

namespace My;

UnexpectedValueException::assertAllEqual($a, $b, $c, $d, $g);


class UnexpectedValueException extends \UnexpectedValueException {

    public static function assertAllEqual(/* $value, ... */) {
        $args = func_get_args();
        if (count(array_unique($args)) > 1) {
            throw new static(sprintf('[%s] are not all equal', join(', ', $args)));
        }
    }

}

回答by George Filippakis

There is a recommendation nowadays... in PSR-12.

现在有一个建议......在PSR-12 中

Expressions in parentheses MAY be split across multiple lines, where each subsequent line is indented at least once. When doing so, the first condition MUST be on the next line. The closing parenthesis and opening brace MUST be placed together on their own line with one space between them. Boolean operators between conditions MUST always be at the beginning or at the end of the line, not a mix of both.

括号中的表达式可以分成多行,其中每一行至少缩进一次。这样做时,第一个条件必须在下一行。右括号和左大括号必须放在它们自己的一行上,它们之间有一个空格。条件之间的布尔运算符必须始终位于行首或行尾,而不是两者的混合。

<?php

if (
    $expr1
    && $expr2
) {
    // if body
} elseif (
    $expr3
    && $expr4
) {
    // elseif body
}

回答by Lemures

I prefer to do it in this style:

我更喜欢这样做:

if (condition1
|| (condition2_1 
    && condition2_2
    && condition2_3)
&& (c3 && c4) {
    // do something
}

But again, keep your if's as simple as possible.

但同样,让你的 if 尽可能简单。

Maybeit's a better idea to separate a big condition in multiple if's.

也许在多个 if 中分离一个大条件是一个更好的主意。

For your question, I would create a function which takes an array and returns true if all &&are met. Then, in my main code you'd have like

对于您的问题,我将创建一个函数,该函数接受一个数组并&&在满足所有条件时返回 true 。然后,在我的主代码中,你会喜欢

$arr = [$a => $b, $b => $c, $c => $d];
// or you can create array of arrays [[$a, $b], [$b, $c] ...]

if (allTrue($arr))
    // do something