20

or die在 PHP 中,您可以通过在遇到某些错误时调用 exit 来处理错误,如下所示:

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

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

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

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

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

4

3 回答 3

27

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


or return不起作用,因为return语言解析器不将其视为“表达式” - 就这么简单。

该关键字or在 PHP 语言中被定义为一个名为 的标记T_LOGICAL_OR,并且似乎定义它的唯一表达式如下所示

 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令牌,然后是另一个表达式。

如您所料, Anexpr也由解析器定义。它可以是 a r_variable,这意味着它是一个允许您读取的变量,也可以是 an expr_without_variable,这是一种表示表达式可以由其他表达式组成的奇特方式。

您可以这样做or die(),因为语言构造die(不是函数!)及其别名exit都由令牌表示T_EXIT,并且T_EXIT被认为是有效的expr_without_variable,而return语句 - 令牌T_RETURN- 不是。

现在,为什么被T_EXIT认为是一个表达式,但T_RETURN不是?老实说,我不知道。也许这只是为了允许or die()您所询问的构造而做出的设计选择。它曾经被广泛使用的事实 - 至少在教程之类的东西中,因为我无法处理大量生产代码 - 似乎暗示这可能是一个有意的选择。您必须询问语言开发人员才能确定。


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

  • 它在运算符优先级列表中非常低,这意味着几乎所有其他表达式都会在它被计算之前被评估
  • 它是一个短路运算符,这意味着or如果第一个操作数返回 ,则不执行第二个操作数( 之后的位)TRUE,因为如果一个操作数TRUEor表达式中,那么它们都是。

有些人认为这种诡计是不利的,因为程序员更难阅读,但只在源代码中节省了几个字符的空间。由于程序员的时间很昂贵,而磁盘空间又很便宜,所以您可以理解为什么人们不喜欢这样。

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

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

您甚至可以在if语句中直接进行变量赋值。有些人仍然觉得这不可读,但大多数人(包括我自己)不同意:

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

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

于 2013-01-18T07:43:23.673 回答
1

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

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

如果是这样,return必须是一个执行“双重退出”的函数,不仅留下它自己的作用域,还留下调用者的作用域。因此 return 与表达式完全不同,它根本不能那样工作。

现在理论上,return 可以是一个表达式,计算结果为(比如说)false,然后退出函数;也许以后的 php 版本会实现这一点。

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

connectMyDB() fallback return false;

像 try...catch 之类的东西,更重要的是。就个人而言,我对“或”做这项工作会更满意,因为它与英语语法配合得很好:“连接或报告失败”。

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

于 2016-01-15T15:55:45.710 回答
0

我也偶然发现了一次。我能找到的只有这个:

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

看看下面的评论:

这不是错误

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

关于错误处理,我建议使用自定义代码或使用自定义处理程序和触发器。例如,后者在此处进行了描述。

于 2013-01-18T06:11:33.990 回答