php empty 函数判断结果为空但实际值却为非空的原因解析

最近我在一个项目中使用 empty 时获取到了一些意料之外的结果。下面是我处理后的调试记录,在这里与你分享了。

var_dump(
  $user->uid,
  empty($user->uid)
);

它的结果是:

string(5) "2955"
bool(true)

结果出人意料。为什么变量的值为字符串,但同时会是空值呢?让我们在 $user->uid 变量上尝试使用其它一些函数来进行判断吧:

var_dump(
  $user->uid,
  empty($user->uid),
  isset($user->uid),
  is_null($user->uid)
);

以上结果为:

string(5) "2955"
bool(true) // empty
bool(false) // isset
bool(false) // is_null

is_null 函数执行结果符合预期判断,empty和isset函数返回了错误结果。

这里让我们来看看 user类的实现代码吧:

class User
{  protected $attributes = [];
  public function __construct(array $attributes)
  {
    $this->attributes = $attributes;
  }
  public function __get($name)
  {
    return $this->attributes[$name] ?? null;
  }
}
 

从上述代码我们可以看到 Person 对象的成员变量是通过 __get 魔术方法从 $attributes 数组中检索出来的。

当将变量传入一个普通函数时,$person->firstName 会先进行取值处理,然后再将获取到的结果作为参数传入函数内。

但是 empty 不是一个函数,而是一种语言结构。所以当将 $user->uid传入 empty时,并不会先进行取值处理。而是会先判断 $user对象成员变量 uid的内容,由于这个变量并未真实存在,所以返回 false。

在正中应用场景下,如果你希望 empty 函数能够正常处理变量,我们需要在类中实现 __isset 魔术方法。

class User
{
  protected $attributes = [];
  public function __construct(array $attributes)
  {
    $this->attributes = $attributes;
  }
  public function __get($name)
  {
    return $this->attributes[$name] ?? null;
  }
  public function __isset($name)
  {
    $attribute = $this->$name;
    return !empty($attribute);
  }
}
 

这是当 empty 进行控制判断时,会使用这个魔术方法来判断最终的结果。

再让我们看看输出结果:

var_dump(
  $user->uid,
  empty($user->uid)
);
 

新的检测结果:

string(5) "2955"
bool(false)

 

1.什么是语言结构
语言结构:就是PHP语言的关键词,语言语法的一部分;它不可以被用户定义或者添加到语言扩展或者库中;它可以有也可以没有变量和返回值。
2.语言结构执行速度快的原因
函数都要先被PHP解析器(Zend引擎)分解成语言结构,所以,函数比语言结构多了一层解析器解析,速度就相对慢了
3.php中语言结构有哪些

echo() 
print() 
die() 
isset() 
unset() 
include(),注意,include_once()是函数 
require(),注意,require_once()是函数 
array() 
list() 
empty() 

4.怎样判断是语言结构还是函数
使用function_exists
eg:

function check($name){
    if(function_exists($name)){
        echo $name.'为函数';
    }else{
        echo $name.'为语言结构';
    }
}
5.语言结构与函数的区别 
1.语言结构比对应功能的函数快 
2.语言结构在错误处理上比较鲁棒,由于是语言关键词,所以不具备再处理的环节 
3.语言结构不能在配置项(php.ini)中禁用,函数则可以。 
4.语言结构不能被用做回调函数

 

posted @ 2018-10-15 17:33  cfYu  阅读(897)  评论(0编辑  收藏  举报