为什么许多PHP开发人员讨厌使用isset()和/或PHP的类似防御功能(例如empty())?


27

在stackoverflow上,我一直看到这个问题:

甚至Pekka(提供了很多可靠的PHP建议)也碰到了可怕的E_NOTICE怪物,并希望有一个比使用更好的解决方案isset()isset()和empty()使代码丑陋

就个人而言,我使用isset()empty()在很多地方来管理我的应用程序的流量。例如:

public function do_something($optional_parameter = NULL) {
    if (!empty($optional_parameter)) {
        // do optional stuff with the contents of $optional_parameter
    }
    // do mandatory stuff
}  

甚至像这样的简单代码段:

if (!isset($_REQUEST['form_var'])) {
    // something's missing, do something about it.
}

对我来说似乎很合逻辑。它看起来不膨胀,看起来像稳定的代码。但是,许多开发人员使用E_NOTICE启用了,从而启动了他们的应用程序,发现了许多令人沮丧的“未初始化的数组索引”通知,然后对检查已定义的变量并使用来“乱丢”其代码感到无所适从isset()

我认为其他语言处理问题的方式也不同。从经验来看,JavaScript不像PHP那样礼貌。未定义的变量通常会停止脚本的执行。另外,(从经验上来讲)我确定像C / C ++这样的语言只会拒绝编译。

那么,PHP开发人员只是懒惰吗?(不是在谈论您,Pekka,我知道您是在重构一个旧的应用程序。)或者其他语言是否比要求程序员首先检查它们是否已被定义更优雅地处理未定义的变量?

(我知道E_NOTICE除了未定义的变量以外,还有其他消息,但这些消息似乎是造成最大麻烦的消息)

附录
到目前为止的答案中,我并不是唯一认为isset()不是代码膨胀的人。所以,我现在想知道,其他语言的程序员是否有与此相呼应的问题?还是这仅仅是一个PHP文化问题?


4
可悲的是,我还看到php开发人员也关闭了“警告”。
Viper_Sb 2010年

哎哟。这可悲的。
斯蒂芬

1
我不是PHP用户,我想知道:为什么需要检查未定义的变量?
温斯顿·埃韦特

2
@Winston:PHP的问题(与许多其他语言相反)是PHP允许许多配置组合。例如,程序员可以决定忽略警告,通知和弃用通知。经验丰富的开发人员将使用error_reporting设置来报告所有内容。PHP还具有许多引发错误和返回状态代码而不是引发异常的函数。人们必须非常熟悉这种语言,以便能够成功地进行防御性编码。许多其他语言不允许选择。严格通常是默认且唯一的选项。
摩尔三世

1
我不喜欢isset(),因为它增加了详细程度。@的更好形式将是一个不错的选择。
卡扎伊2011年

Answers:


34

我编码到E_STRICT,别无其他。

使用empty和isset检查不会使您的代码难看,但会使您的代码更冗长。在我看来,使用它们绝对会发生什么最坏的事情?我再输入几个字符。

验证不使用它们的后果,至少是警告。


7
我的开发环境也是E_STRICT。我抑制了生产中的所有错误,但这只是为了确保在开发过程中没有遗漏。
斯蒂芬

2
+1乔希,我也一样。当您使用E_STRICT进行编程时,您会知道代码永远不会感到惊讶。唯一的办法,飞。
EricBoersma

3
@Stephen:始终关闭生产错误。不过,那只是一个安全网。发展(IMO)永远是E_STRICT。编写代码并解决所有警告和错误。
乔什·K

你在骗我吗 :)
Stephen

@斯蒂芬:我同意。:)
Josh K 2010年

17

我认为有关未知元素的通知是PHP中的一个设计错误。我不确定现在是否可以解决该错误,但是它会产生很多样板代码,例如if(isset($foo['abc']) && $foo['abc'] == '123')-此代码不应具有该代码isset,因为其目的是检查特定位置是否有“ 123”,$foo以及是否没有任何内容。绝对不是“ 123”。您必须编写两倍于此的代码的唯一原因是由于PHP中不幸的设计错误。而且,不幸的是,通知在PHP 中非常昂贵,因此,对于性能而言,禁用通知并不是代码的一种选择。

所以是的,它确实使代码丑陋,恕我直言,这确实使我烦恼。这不是因为缺乏经验-我从1998年开始使用PHP,我记得当时有.php3扩展,它的意思是“这不是PHP 2”。也许我很懒:)但是,懒惰-至少是某种类型的懒惰-对于程序员是一种美德。

另一方面,可以有效地使用issetempty-就像原始帖子中的-一样。我只是认为PHP对isset/empty真正不需要的地方的警告过于狂热。


3
对。这是冗长的问题。 $eg = isset($_GET['eg'])? $_GET['eg'] : null;非常荒谬。我真的希望还有另一个本身不是“抑制错误”的运算符来代表$eg = @$_GET['eg'];“不接受此数组键为空” 的简短含义。这些天,我倾向于使用短函数。
卡扎伊2011年

7
同意 4年后,输入Null Coalesce运算符:wiki.php.net/rfc/isset_ternary给我们$eg = $_GET['eg'] ?? null;
Steve

或者现在就使用错误抑制运算符(例如)进行操作$eg = @$_GET['eg'] ?: null;。我通常不使用它,但是在这种情况下,我们明确希望该错误并决定忽略它。它比空合并的字符长一个字符,并且效果不佳(它抑制了所有错误,并且ArrayAccess可能在其中执行时髦的操作,而不仅仅是数组),但总的来说,它可以完成这项工作。
El Yobo 2015年

12

我相信PHP作为一种自由语言,可以在网络上解释和使用,非专业,未经培训的编码人员中,有很大比例的人没有完全意识到为什么要进行防御性编码,而只是将警告视为另一个不必要的错误。 。

我一直都从初级开发人员和自学成才的脚本编码人员那里听到以下几点:

  • 如果无论如何都会存在一个变量,为什么还要初始化呢?
  • 为什么在使用某些东西之前先检查是否存在某种东西,无论如何,未定义都等于假?
  • 如果我在@前面加上前缀,则可以修复我的代码,为什么使事情复杂化?

如果他们从未经历过强类型的语言,或者经历了未声明/未实例化的变量的陷阱,那么他们会令人信服。我发现他们通常会在经历了一个小时左右的调试代码乐趣之后就屈服了,因为发现它是变量名中的错字,造成了麻烦。

另一个强大的因素是PHP在Web行业中的使用,与安全性和代码质量相比,PHP对吞吐量的关注更大。


10
“我相信PHP [...]中非专业,未经训练的编码人员比例很高。”作为一个专门的PHP开发人员,我不能完全同意您的意见。+1
斯蒂芬·2010年

@Stephen好吧,尽管我确实接受过正规教育,但最近我主要使用PHP和jQuery进行编码,但是您之前认为自己是专业人士的代码……有时违反了信念。;-)
Orbling 2010年

1
我认为这是PHP的真正问题。除了一些语言上的怪异现象(他们在每个新版本中都在慢慢解决)之外,还有一种业余爱好。我可以想象成为一名专业的PHP开发人员有时会感到沮丧,因为您正在与“来自角落的老板的侄子”进行比较。
Erik van Brakel 2010年

1
@Erik PHP在十年前是Perl的一个相对较差的亲戚,现在它是一种相当合理的解释语言,尤其是对于Web使用而言。像Facebook这样的公司使用它是有原因的。但是由于它随处可见,因此业余爱好者广泛使用它,这损害了声誉。
2010年

5

是的,他们很懒。反正很多...

不幸的是,许多PHP编码人员的心态是“如果依靠语言来处理因缺少变量等导致的错误,从而更快地获得相同的最终结果,那么防御性的编码就毫无意义。” 我知道,我已经和其中的几个一起工作了。

当他们由于缺乏正确的错误处理和报告而无法使用实时服务器几个小时时,他们往往也会神秘地去吃早饭。


5
-1为关于PHP编码器的主观意见。
乔什·K

4
@Josh,已经有4 1/2年的高级PHP编码器,自1999年以来就断断续续地对PHP进行编码,恐怕我有些主观。我应该具备“另一方面,经验丰富的PHP编码人员不会偷懒并且不能正确执行操作” ...
Gruffputs,2010年

1
你应该有的。
乔什(Josh K)2010年

5

我尝试通过避免将数组用作数据传输对象来避免使用isset()和empty()。创建一个可配置为接受具有默认值的有限属性集的类,并验证对这些属性的输入。它甚至可以实现ArrayAccess接口,因此您可以像使用数组一样使用它。当有人尝试将错误的实体类型传递给您的方法时,这还允许您在方法签名中使用类型提示来捕获错误。


一个非常有趣的方法。
托比,2010年

2

我所质疑的问题之一,所以让我重申一下。

许多开发人员将大量的存在误认为isset()是质量标志。它具有可靠性的外观,甚至有人将其视为安全功能。

但是您必须考虑到PHP不是编译语言。这是一种具有动态类型系统的脚本语言。E_NOTICE错误仅是名称错误。而且,如果isset出于抑制提示的目的而使用了大量的代码,那么实际上您只是在针对该语言进行编码

那么,PHP开发人员只是懒惰吗?

如果您看到大量的通知和警告,情况确实如此。很多新手都不在乎通知,这通常是完全禁用的结果error_reporting(0)

但是,您会误以为其他开发人员没有仅仅因为E_NOTICE未被@或isset抑制而无法识别E_NOTICE。至少那是我保留通知问题背后的意图。它们不是要摆脱的东西,但有时还是重要的调试信息。

像所有概括一样,对isset的粗心使用不会导致最佳代码。它区分哪里是非常重要的issetempty有必要的,他们在哪里句法盐

还是这仅仅是一个PHP文化问题?

不,未定义的变量“错误”不仅仅是一个PHP问题。Bash,TCL和Perl或JavaScript允许使用未定义的变量。但是,这种内在的语言功能并不被视为缺陷。有类似的语言构造可以检查未定义的值。但是,由于undef值没有错误地描述为“错误”,因此它们没有像PHP那样经常使用。


1

有趣。我几乎从未使用过isset()。我的PHP代码很少处于不知道是否首先设置变量的状态。每个使用的GET或POST变量都可以通过一个函数访问,该函数将为其提供默认值(如果不存在)。函数调用中的默认值通常显式设置为0或空字符串。


+1。传递给函数或类方法是一个很好的解决方案。其实,我不要这么做,但在紧要关头,我上面的例子仍然显得干净和未臃肿给我。
斯蒂芬

0

我用isset和空很多。但是大多数情况下,您会提到这些地方,例如$ _REQUEST处理,以防有人弄乱参数。在我可以控制所有变量的情况下,我发现我通常不需要它们。


0

我不喜欢使用isset,但是如果有大量代码是由另一个人完成的,那么这可能是一种节省。我在下面编写了wee代码来解决此问题,而不是使用isset()isseter($ a,$ b)会在$ a未定义或为空或函数返回null的情况下返回$ b。任何改进,欢迎:

//returns var or NULL (if undefined)
//$reserve optional second value is returned as $default if undefined
function isseter(&$default,&$reserve=NULL)
{
$default = isset($default) ? $default : NULL;
$reserve = isset($reserve) ? $reserve : NULL;
if ((!$default) && ($reserve)) $default=$reserve;
return $default;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.