错误使用empty()函数

来源:互联网 发布:软件flash是什么意思啊 编辑:程序博客网 时间:2024/06/02 04:05

一些PHP开发人员喜欢用empty()函数去对变量或表达式做布尔判断,但在某些情况下会让人很困惑。

首先我们来看看PHP中的数组Array和数组对象ArrayObject。看上去好像没什么区别,都是一样的。真的这样吗?

// PHP 5.0 or later: $array = []; var_dump(empty($array));        // outputs bool(true)  $array = new ArrayObject(); var_dump(empty($array));        // outputs bool(false) // why don't these both produce the same output?

让事情变得更复杂些,看看下面的代码:

// Prior to PHP 5.0: $array = []; var_dump(empty($array));        // outputs bool(false)  $array = new ArrayObject(); var_dump(empty($array));        // outputs bool(false)

很不幸的是,上面这种方法很受欢迎。例如,在Zend Framework 2中,Zend\Db\TableGateway 在 TableGateway::select() 结果集上调用 current() 方法返回数据集时就是这么干的。开发人员很容易就会踩到这个坑。

为了避免这些问题,检查一个数组是否为空最后的办法是用 count() 函数:

// Note that this work in ALL versions of PHP (both pre and post 5.0): $array = []; var_dump(count($array));        // outputs int(0) $array = new ArrayObject(); var_dump(count($array));        // outputs int(0)

在这顺便提一下,因为PHP中会将数值0认为是布尔值false,因此 count() 函数可以直接用在 if 条件语句的条件判断中来判断数组是否为空。另外,count() 函数对于数组来说复杂度为O(1),因此用 count() 函数是一个明智的选择。

再来看一个用 empty() 函数很危险的例子。当在魔术方法 __get() 中结合使用 empty() 函数时,也是很危险的。我们来定义两个类,每个类都有一个 test 属性。

首先我们定义 Regular 类,有一个 test 属性:

class Regular {     public $test = 'value'; }

然后我们定义 Magic 类,并用 __get() 魔术方法来访问它的 test 属性:

class Magic {     private $values = ['test' => 'value'];     public function __get($key)     {         if (isset($this->values[$key])) {             return $this->values[$key];         }     } }

好了。我们现在来看看访问各个类的 test 属性会发生什么:

$regular = new Regular(); var_dump($regular->test);    // outputs string(4) "value" $magic = new Magic(); var_dump($magic->test);      // outputs string(4) "value"

到目前为止,都还是正常的,没有让我们感到迷糊。

但在 test 属性上使用 empty() 函数会怎么样呢?

var_dump(empty($regular->test));    // outputs bool(false) var_dump(empty($magic->test));      // outputs bool(true)

结果是不是很意外?

很不幸的是,如果一个类使用魔法 __get() 函数来访问类属性的值,没有简单的方法来检查属性值是否为空或是不存在。在类作用域外,你只能检查是否返回 null 值,但这并不一定意味着没有设置相应的键,因为键值可以被设置为 null 。

相比之下,如果我们访问 Regular 类的一个不存在的属性,则会得到一个类似下面的Notice消息:

Notice: Undefined property: Regular::$nonExistantTest in /path/to/test.php on line 10 Call Stack:     0.0012     234704   1. {main}() /path/to/test.php:0

因此,对于 empty() 函数,我们要小心的使用,要不然的话就会结果出乎意料,甚至潜在的误导你。

0 0