哪个在PHP中更好:用'@'抑制警告或用isset()运行额外的检查?

moj*_*uba 9 php isset

例如,如果我实现一些简单的对象缓存,哪种方法更快?

1. return isset($cache[$cls]) ? $cache[$cls] : $cache[$cls] = new $cls;

2. return @$cache[$cls] ?: $cache[$cls] = new $cls;
Run Code Online (Sandbox Code Playgroud)

我读某处@需要花费大量时间才能执行(我想知道为什么),特别是在实际发出和禁止警告/通知时.isset()另一方面,这意味着额外的哈希查找.哪个更好,为什么?

我确实希望在开发和生产服务器上全局保持E_NOTICE.

jim*_*imp 9

isset()方法是更好的.它是明确声明索引可能未定义的代码.抑制错误是编码邋.

根据这篇文章10加速PHP的性能提示,警告需要额外的执行时间,并声称@运营商"昂贵".

事先清理警告和错误也可以防止使用@错误抑制,这很昂贵.

此外,@不会抑制自定义错误处理程序的错误:

http://www.php.net/manual/en/language.operators.errorcontrol.php

如果您使用set_error_handler()设置了自定义错误处理函数,那么它仍然会被调用,但是这个自定义错误处理程序可以(并且应该)调用error_reporting(),当触发错误的调用前面有@时,它将返回0 .

如果启用了track_errors功能,则表达式生成的任何错误消息都将保存在变量$ php_errormsg中.此变量将在每个错误上被覆盖,因此如果要使用它,请提前检查.


Mik*_*ant 7

我不担心哪种方法更快.这是微观优化.我会更担心哪些是更易读的代码和更好的编码实践.

我肯定更喜欢你的第一个选项,因为你的意图更清晰.此外,最好通过始终明确地测试变量以确保获得您期望获得的内容来避免边缘条件问题.例如,如果存储的类$cache[$cls]不是类型$cls怎么办?

就个人而言,如果我通常不希望未设置$ cache上的索引,那么我也会将错误处理放在那里而不是使用三元操作.如果我可以合理地期望该索引会定期取消,那么我会让类$cls表现为单例并让你的代码像

return $cls::get_instance();
Run Code Online (Sandbox Code Playgroud)

  • @mojuba接缝不可读的部分是"@ $ cache [$ cls]?:",它告诉我你的可读性.它告诉我你正在尽可能地缩短你的代码,因为你的硬盘驱动器只有大约2K的可用空间. (6认同)
  • 成千上万的代码行不是很多 - 数百万.除非你有疯狂的交通水平,否则这种微小的速度差异不会对你产生影响...... (3认同)
  • 我不认为第二行是可读和干净的 (2认同)

Tch*_*upi 7

@暂时改变error_reporting状态,这就是说它需要时间的原因.

如果您期望某个值,那么验证它的第一件事就是检查它是否已定义.如果你有通知,那可能是因为你错过了什么.isset()在我看来,使用是一种很好的做法.


moj*_*uba 3

我对这两种情况进行了计时测试,使用不同长度的哈希键,还使用哈希表的不同命中/未命中率,以及使用和不使用E_NOTICE.

结果是:使用error_reporting(E_ALL)该变体的速度比使用 20-30% 的isset()速度快。@使用的平台:OS X 10.8 上的命令行 PHP 5.4.7。

然而,error_reporting(E_ALL & ~E_NOTICE)对于短哈希键,差异在 1-2% 之内,对于较长哈希键(16 个字符),差异高达 10%。

请注意,第一个变体执行 2 次哈希表查找,而 with 的变体@仅执行一次查找。

因此,@在所有场景下都比较差,不知道是否有优化的计划。