如果我在相同的IF语句中放入一个isset(),为什么不通知PHP,该数组索引不存在?

时间:2014-06-05 13:32:29

标签: php isset comparison-operators short-circuiting

情况:我们有一小段PHP代码检查变量是否具有某个值,但由于数组索引及其值尚未设置,这将创建一个E_NOTICE错误:

这会触发通知

<?php

    $arr = array();

    if ($arr['name']=='john') {
        echo('This should not work');
    } else {
        echo('In your computer, ignoring your notice');
    }

这引起了很好的注意:

PHP Notice:  Undefined index: name in /home/hvanmegen/test.php on line 5
PHP Stack trace:
PHP   1. {main}() /home/hvanmegen/test.php:0

现在请向我解释一下,如果该值检查会抛出错误,下面打印的代码如何正常工作而不会抛出相同的异常?!?!

这不会触发通知!

<?php

    $arr = array();

    if (isset($arr['name']) && $arr['name']=='john') {
        echo('This should not work');
    } else {
        echo('In your computer, ignoring your notice');
    }

输出:

In your computer, ignoring your notice

一旦返回第一个错误或其他东西,AND检查是否中止/抛出?

当比较列表中触发第一个错误时,PHP是否只跳过第二次检查并且从未实际执行第二次检查?

此外,将两个if语句分开是否被认为是良好的编码习惯,或者我在编码方面有点过于陈旧?人们会认为检查这个的正确方法是:

<?php

    $arr = array();

    if (isset($arr['name'])) {
        if ($arr['name']=='john') {
            echo('Hi john');
        } else {
            echo('Hi not-john, where is john?');
        }
    } else {
        echo('I cannot check what I do not have');
    }

输出:

I cannot check what I do not have

是否只是我的强迫症想要放置&#39; isset()&#39;在另一个声明之外还是我的方法完全是多余的和过时的?或者我是否坚持你应该用尽可能多的常用语言编写代码的想法。 (使用与语言无关的语法,尽可能简单地从一种语言切换到下一种语言)?

其他编程和脚本语言(Java,C ++ / C#,Javascript,Python)如何处理这个问题?

4 个答案:

答案 0 :(得分:9)

  

当比较列表中触发第一个错误时,PHP是否只跳过第二次检查并且从未实际执行第二次检查?

是。它被称为short-circuit evaluation

&&(和)如果左侧为假,则不评估右侧,因为结果必须为假。

||(或)如果左侧为真,则不评估右侧,因为结果必须为真。

  

另外,将两个if语句分开是否被认为是良好的编码习惯,或者我在编码方面有点过于陈旧?

虽然编码风格非常个人化,但一旦理解了短路评估,就没有必要将它们分开。我相信在这种情况下,大多数程序员会将条件保持在一个if,特别是因为它们密切相关,并且基本上是检查同一事物的两个步骤。

  

其他编程和脚本语言(Java,C ++ / C#,JavaScript,Python)如何处理这个问题?

与PHP相同。

答案 1 :(得分:3)

if (isset($arr['name']) && $arr['name']=='john')

肯定是&&运算符如果第一个条件是false,编译器或解释器不会浪费时间检查其他条件,因为它没用。因此,在这种情况下,不评估第二个条件。

再次if (isset($arr['name'])) {这个条件是假的,所以它会跳转到其他地方。

echo('I cannot check what I do not have');

答案 2 :(得分:1)

PHP isset不是一个函数。 它是一个内置的,我怀疑它有一些语言水平的魔力。这就是你在第二种情况下没有得到警告的原因。

我通常会编写一个这样的辅助函数来处理这个问题:

function check($array, $key, $expected) {
    if (!isset($array[$key]) return false;
    return $array[$key] == $expected;
}
  

PHP是否只是跳过第二次检查而从未实际执行过     每当在比较列表中触发第一个错误时进行第二次检查??

是的,PHP中的布尔运算符执行short-curcuit evaluation:子表达式从左到右进行求值,一旦解释器知道足够多,它就会返回而不对剩余的子表达式进行评估。

  

其他编程和脚本如何?     语言(Java,C ++ / C#,Javascript,Python)处理这个?

C ++默认处理它,构造value_type(Effectivly,返回一个新的空字符串,插入到映射的索引中。)并且有其他方法可以不经修改地访问。

Ruby返回null或构造函数中指定的默认值。

PHP有点烦人,在某些地方默默地失败,并在不期望的其他地方发出警告。

如果我不关心我写的不存在的密钥:     if(check($ arr,'name',john')){         回声('嗨约翰');     } else {         回声('我不知道你是谁。');     }

答案 3 :(得分:-2)

  if ($arr['name']=='john') { ...

如果您没有带有“name”键的数组元素,则会出现错误。

  isset($arr['name'])
另一方面,

只检查是否有一个带有'name'键的元素。 它只是循环遍历键数组(在空数组上非常快)并返回true键存在。

结论:如果你访问一个数组元素$ arr ['name']你应该知道有这样一个元素。如果您不确定首先检查是否存在isset($ arr ['name'])

希望它有所帮助!