PHP - 如果/否则,for,foreach,while - 没有花括号?

63

我一直想知道但从未弄明白的是PHP中的快捷方式。

我正在编写一个带有foreach循环的函数,并且里面只有一条语句。我尝试省略花括号,就像在if/else控制结构中一样,结果它能够正常工作而没有错误。

foreach($var as $value)
    $arr[] = $value;

现在我尝试以相同的方式使用它,但在其中加入了一个if/else块。再次运行,没有错误。

foreach($var as $value)
    if(1 + 1 == 2) {
        $arr[] = $value;
    };

然后我想:"为什么这个可以工作?" 然后我省略了分号。仍然起作用。所以,我尝试在 foreach 循环内部使用 if/else 语句,而不使用花括号,再次,仍然起作用,没有错误。但是,foreach 循环现在真的结束/关闭了吗?

foreach($var as $value)
    if(1 + 1 == 2)
        $arr[] = $value;

我至少又忘记了写分号,并且(如预期的)出现了解析错误。

所以我的一个大问题是:在哪些结构/循环/函数中可以省略花括号?我知道可以在ifelse中这样做。但是whileforforeach呢?

是的,我知道编写没有花括号的代码不安全、不明智等等,并且有像$condition ? true : false;if: doSomething(); endif;endfor;endforeach;这样的缩写。我不想学习缩写,我只想理解在什么情况下可以省略花括号。


4
顺便提一下,在右括号后面不需要加分号。这样做的语法意义是在它们之间添加一个空语句。这对于所有类C语言来说都是正确的,但在C和C++中对structclass的声明除外。 - Eric
你需要学习语句和表达式的区别,才能理解何时可以省略花括号。然后,仍然需要对表达式的内聚性有一个强大的理解。 - mario
14个回答

100

当你省略大括号时,它会将下一条语句视为条件体。

if ($x) echo 'foo';

等同于

if ($x) { echo 'foo'; }

但请记住

if ($x)
  echo 'foo';
  echo 'bar';

将始终打印“bar”

内部情况恰好相反:if仅查看下一个表达式,但PHP将{}中的所有内容视为单个“分组”表达式。

其他控制语句(foreach等)也是如此。


非常好的简短解释,谢谢! :) 它适用于每个控制结构吗? - headacheCoder
1
@headacheCoder 是的,它对于 forwhileforeachif 都有效。而且,这对于每一种带有类 C 语法的语言都是如此。请注意 @tkone 的回答,总是使用大括号是良好的编程实践。 - Eric
@Eric 是的,我注意到了,但那不是我的问题的一部分。我总是尝试编写干净和可用的代码。这更多地是关于理解语法。 :) - headacheCoder
3
有一个例外;它不能与异常一起使用。完全是故意的双关语。 - Francisco Presencia
@FrankPresenciaFandos 你是指 try-catch 吗?因为 Exception 首先就是一个类 ;) 是的,try-catch 的替代语法根本不存在(不知道这是否有更深层次的原因,还是只是“被遗忘”了)。 - KingCrunch
显示剩余5条评论

37

有些地方你们可以这样做,但是你们永远不应该。

明确总比隐含好。

谁知道你什么时候需要回去修改旧代码。很容易忽略那些东西,而且没有任何收获。


16

如果你只有一个参数,那么它将工作正常!但是,如果你想省略花括号,你可以使用冒号和结束符。

例子:

if(a < 1 ) :
    echo "a is less than 1";
else :
    echo "a is greater than 1";
endif;

10

正如之前所说,您不想学习速记,并且接受的答案给出了省略 花括号 的很好的示例,但还有一些需要补充的地方。正如您所看到的,在 if ($x) echo 'foo'; 的情况下省略 花括号 是可以的。代码没有任何问题,没有性能或其他问题,并且其他开发人员也可以阅读。示例还向您展示,如果您编写

if ($x)
    echo 'foo';
    echo 'bar';

代替

if ($x)
    echo 'foo';

echo 'bar';

如果你不想打印bar,但是出现了不需要的结果,那么如果你的代码充满这样的语句,会使你自己难以阅读代码,其他人更难阅读。

我不想学习速记,我只想理解可以在什么条件下和何处可以省略花括号。

这些问题密切相关,因此如果您真的想要理解在哪里可以省略花括号,那么必须了解或至少知道速记的相关知识,请阅读以下两篇文章:

  1. PHP控制结构
  2. PHP三元运算符和表达式

所以我的大问题是:在哪些结构/循环/函数中可以省略花括号?

花括号不是必需的,然而为了可读性和维护性,许多开发人员认为不包含它们是不好的风格。前面提到的2个链接应该为您提供了必要的信息,使您能够自行决定何时可以省略花括号。 例如,以下代码片段都完全相同且合法:

使用花括号

if (PHP_VERSION_ID < 70000)
{
    print "PHP >= 7.0 required yours is ";
    print phpversion();
    print "\n";
    exit(1);
}

与...相同

if (PHP_VERSION_ID < 70000) :
    print "PHP >= 7.0 required yours is ";
    print phpversion();
    print "\n";
    exit(1);
endif;

或者您可以使用点运算符

if (PHP_VERSION_ID < 80000)
    (print "PHP >= 7.0 required yours is ") . (print phpversion()) . (print "\n") . exit(1);

你可以利用三目运算符,甚至可以省略掉if关键字和花括号

(PHP_VERSION_ID > 70000) ?: (print "PHP >= 7.0 required yours is ") . (print phpversion()) . (print "\n") . exit(1);

由于我们只打印,因此可以缩短代码并剥离一些print字符串函数,这些函数在语句中没有花括号表示多个函数。

(PHP_VERSION_ID > 70000) ?: (print "PHP >= 7.0 required yours is " . phpversion() . "\n") . exit(1);

从php 7开始我们可以使用Null合并运算符

(PHP_VERSION_ID > 70000) ?: null ?? (print "PHP >= 7.0 required yours is ".phpversion() . "\n") . exit(1);

可以看到,有很多方法可以得到完全相同的结果。这不仅适用于这个if示例,还适用于结构/循环/函数。因此,对于您的重要问题并没有一个明确的答案。主要需要考虑以下几点:

  1. 编写的代码是否易于维护。
  2. 省略花括号会带来什么好处,您自己能回答吗?

哦,我不知道他们在 Elvis 运算符中添加了一个 null 合并运算符...很棒。但是运算符的哪一侧是 null,并且它是否允许在条件块中使用未设置的变量? - Ber
1
$I_want_value = $if_im_not_null_use_me ?? $if_first_is_null_use_me ?? $if_second_is_null_use_me; 这样,如果前一个变量为NULL,您可以有尽可能多的替代选择。PHP 7新特性 - mkungla
有趣,所以它是一个无限制的运算符...但它能在未定义的变量上工作吗?我会查看文档。我认为这就是使用null合并运算符的唯一目的,否则为什么不只使用Elvis。?:) - Ber
啊,文档说 ?? 可以在未设置的变量上工作。太好了!这可能会减少 PHP 中 isset() 调用的大量冗余代码。 - Ber

3

您可以将其用于简单的事情,例如:

if($a === true) continue;

但是对于一些更为复杂的子条件,这可能会给你带来问题:

    $a = false;
    $b = false;
    if ($a === true)
        if ($b === true)
            echo 1;
    else
        echo 2;

使用上述代码,您希望看到的输出应该是“2”,但实际上不会出现。


2
为补充@Marko的答案,当使用点运算符时,应该将每个操作用括号括起来,否则它会倒置顺序。
例如,下面的代码将打印“PHP >= 7.0 required yours is 5.6.15”。
(print "PHP >= 7.0 required yours is ") . (print phpversion()) . (print "\n");

虽然这将打印出5.6.151PHP >= 7.0 required yours is 1

print("PHP >= 7.0 required yours is ") . print(phpversion()) . print("\n");

您可以使用“and”运算符来实现此目的。如下所示:
if (PHP_VERSION_ID < 70000)
    print("PHP >= 7.0 required yours is ") and
    print(phpversion()) and
    print("\n");

2

我在我的PHP模板中省略了花括号。例如,您可以按照以下方式使用循环:

<ul>
    <?php foreach ($var as $value): ?>
        <li><?php echo $value; ?></li>
    <?php endforeach; ?>
</ul>

10
可替代的语法是不同的。 - KingCrunch
1
OP甚至说他知道替代语法,但这不是问题所在。 - CommandZ

1

针对单行语句。

如果您尝试执行

foreach($array as $x => $y)
    $do_something = $x;
    $do_something_else = $y;

除非我弄错了,php解释器将把foreach语句下的第二行视为隐含大括号之外的内容。

由于缩进,如果您在以后的某个时间回到此代码,或者其他开发人员查看您的工作,这将会令人困惑。

因此,通常最好始终使用大括号来配合这些语句。这将节省以后的头痛和混乱。


你是对的。第二行不在循环内。只有紧接着的表达式在循环内。 - CommandZ

1
什么时候可以省略大括号,在哪些结构/循环/函数中? 我知道在if和else中可以省略,但while、for和foreach呢?
对于if/else,可以使用以下结构来实现单个多个语句而不需要大括号:
<?php
  if ($x):
    echo 'foo';
    echo 'bar';
  else:
    echo 'nofoo';
    echo 'nobar';
  endif;
?>

此答案所述

对于whileforforeach,只允许使用没有花括号的单语句

<?php
foreach($array as $x => $y)
    $do_something = $x;
?>

0

当你的从句之后只有一个表达式时,这是可能的。

例如,

foreach($var as $value)
    if(1 + 1 == 2) {
        $arr[] = $value;
    };

是正确的,但是

foreach($var as $value)
    $somevar = $var;
    if(1 + 1 == 2) {
        $arr[] = $value;
    };

这不是,而且 PHP 解释器会认为 if 语句在 foreach 外面


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