在PHP中,为什么“或die()”工作,但“或返回”不工作?

时间:2013-01-18 05:54:33

标签: php error-handling return internals parse-error

在PHP中,当遇到某些错误时,您可以通过调用or die来退出错误,例如:

$handle = fopen($location, "r") or die("Couldn't get handle");

使用die()不是处理错误的好方法。我宁愿返回一个错误代码,以便父函数可以决定做什么,而不仅仅是不正确地结束脚本并向用户显示错误。

但是,当我尝试将or die替换为or return时,PHP显示错误,如下所示:

$handle = fopen($location, "r") or return 0;

为什么or die()有效,而or return 0无效?

3 个答案:

答案 0 :(得分:26)

我想感谢你提出这个问题,因为我不知道你不能在PHP中执行or return。当我测试时,我和你一样惊讶。这个问题给了我一个很好的借口,可以在PHP的内部进行一些研究和游戏,这实际上非常有趣。但是,我不是PHP内部的专家,所以以下是PHP内部的外行人看法,尽管我认为它相当准确。


or return无效,因为return并未被视为"表达"语言分析器 - 简单。

关键字or在PHP语言中定义为名为T_LOGICAL_OR的标记,并且似乎定义的唯一表达式看起来像this

 expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
不要担心大括号中的位 - 只是定义了实际的"或"处理逻辑。你留下的是expr T_LOGICAL_OR expr,它只是说它是一个有效的表达式,有一个表达式,后跟T_LOGICAL_OR标记,后跟另一个表达式。

解析器也定义expr,正如您所期望的那样。它可以是r_variable,只是意味着它是您允许阅读的变量,或expr_without_variable,这是一种表达表达式的奇特方式用其他表达方式构成。

您可以执行or die(),因为语言构造die(不是函数!)及其别名exit都由标记T_EXIT表示,{{1被视为有效T_EXIT,而expr_without_variable语句 - 令牌return - 则不是。

现在,为什么T_RETURN被视为表达式而T_EXIT不是?老实说,我不知道。也许这只是一个设计选择,只是为了允许您提出的T_RETURN结构。以前它被广泛使用的事实 - 至少在教程之类的东西,因为我不能说出大量的生产代码 - 似乎暗示这可能是一个有意的选择。您必须要求语言开发人员确切知道。


所有这些都说明了,这不重要。虽然or die()构造在几年前的教程(见上文)中似乎无处不在,但它并不是真正推荐的,因为它是"聪明的代码"的一个例子。 or die()不是自己的构造,而是使用 - 有些人可能会说滥用 - 使用or die()运算符的两个副作用的技巧:

  • 它在运算符优先级列表中非常低,这意味着实际上每个其他表达式都会在
  • 之前进行评估
  • 它是一个短路运算符,这意味着如果第一个操作数返回or,则不执行第二个操作数(or之后的位),因为如果一个操作数是{{1在TRUE表达式中,它们都是。

有些人认为这种技巧是不利的,因为程序员更难阅读但只能在源代码中保存一些空格字符。由于程序员时间昂贵,磁盘空间便宜,你可以看出为什么人们不喜欢这样。

相反,您应该通过将代码扩展为完整的TRUE语句来明确表达您的意图:

or

您甚至可以在if语句中执行变量赋值。有些人仍然认为这是不可读的,但大多数人(包括我自己)不同意:

$handle = fopen($location, "r");
if ($handle) {
  // process the file
} else {
  return 0;
}

最后一件事:按照惯例,将if作为状态代码返回表示成功,因此您可能希望返回一个不同的值来表示您无法打开该文件。

答案 1 :(得分:0)

我也偶然发现了一次。我能找到的就是:

https://bugs.php.net/bug.php?id=40712

请看下面的评论:

  

这不是错误

我在文档中搜索过,我认为这是因为return 0是一个陈述,而die()本质上是一个表达式。您无法运行$handle = return 0;,但$handle = fun();是有效代码。

关于错误处理,我建议使用自定义代码或使用自定义处理程序和触发器。例如,后者为described here

答案 2 :(得分:0)

返回相当特殊 - 它不能像函数一样,因为它是退出函数的工具。想象一下:

if(1==1) return();  // say what??

如果是这样的话, return 必须是一个执行"双退出"的功能,不仅留下自己的范围,而且留下来电者,太。因此,回归不仅仅是一种表达方式,它根本无法以这种方式运作。

现在理论上,return可以是一个表达式,其评估为(假设)false,然后退出函数;也许以后的php版本会实现这个。

同样的事情适用于转到,这将成为一个后备的魅力;是的,后备是必要的,并且经常使代码可读,所以如果有人抱怨"聪明的代码" (这当然是一个好点)也许PHP应该有一些"官方"做这样的事情的方式:

connectMyDB() fallback return false;

像尝试......抓住的东西,更重要的是。就个人而言,我对#34;或者#34;感到非常高兴。做这项工作,因为它与英语语法配合得很好:"连接或报告失败"。

TLDR:你绝对正确:return,goto,break - 它们都不起作用。容易理解为什么但仍然很烦人。