__get访问器上的PHP empty()

时间:2010-01-11 23:52:28

标签: php oop

使用PHP 5.3将empty()应用于通过__get()重载函数获取的动态对象属性时,我遇到了奇怪/非直观的行为。请考虑以下代码段:

<?php

class Test {

  protected $_data= array(
   'id'=> 23,
   'name'=> 'my string'
  );

  function __get($k) {
    return $this->_data[$k];
  }

}

$test= new Test();
var_dump("Accessing directly:");
var_dump($test->name);
var_dump($test->id);
var_dump(empty($test->name));
var_dump(empty($test->id));

var_dump("Accessing after variable assignment:");
$name= $test->name;
$id= $test->id;
var_dump($name);
var_dump($id);
var_dump(empty($name));
var_dump(empty($id));

?>

此功能的输出如下。比较第一个和第二个结果集上empty()检查的结果:

设置#1,意外结果:

string(19) "Accessing directly:"
string(9) "my string"
int(23)
bool(true)
bool(true)

期望Set#1返回与Set#2相同的内容:

string(36) "Accessing after variable assignment:"
string(9) "my string"
int(23)
bool(false)
bool(false)

这真是令人费解和不直观。对象属性输出非空字符串,但empty()认为它们是空字符串。这是怎么回事?

2 个答案:

答案 0 :(得分:33)

基于对empty的手册页和注释(isset和/或双下划线的Ctrl-F)的阅读,看起来这是已知的行为,如果你想要{{1} }和__set方法和__get一起玩得很好,有一个隐含的假设你也实现了empty魔法。

这有点不直观和令人困惑,但大多数元编程都会发生这种情况,特别是在像PHP这样的系统中。

答案 1 :(得分:4)

在此示例中,empty()调用__isset()重载函数,而不是__get()重载函数。试试这个:

class Test {

  protected $_data= array(
   'id'=> 23,
   'name'=> 'my string'
  );

  function __get($k) {
    return $this->_data[$k];
  }

  function __isset($k) {
    return isset($this->_data[$k]);
  }

}