如何在PHP中检查一个对象是否为空?

124

如何在PHP中判断一个对象是否为空。

以下是代码,其中$obj保存了XML数据。我该如何检查它是否为空?

我的代码:

$obj = simplexml_load_file($url);

可能是PHP对象持有XML数据的重复问题。 - Pekka
可能是如何在PHP中检查对象是否为空?的重复问题。 - kenorb
15个回答

153

你可以将其强制转换为数组,然后检查它是否为空。

$arr = (array)$obj;
if (!$arr) {
    // do stuff
}

9
类型转换对我不起作用,因为我遇到了错误: PHP解析错误:语法错误,(array) (T_ARRAY_CAST)的'(array)' (array)不期望出现在...我使用的是PHP 5.4.28版本,第一个选项(包含两行代码)适用于我。 - Coanda
上传WordPress插件时遇到了相同的错误,看起来他们也使用较旧版本的PHP。 - Asaf
4
empty()函数并不是用来检查数组是否为空的,empty($var)等同于(!isset($var) || !$var)。你可以用!$arr来代替empty($arr),因为array() == FALSE - Timothy Zorn
3
在PHP 5.4+中,empty((array) $obj)无法工作的原因与一行类型转换无关。出现错误是因为empty()函数会获取传递给它的变量的引用,在进行类型转换时无法获得引用,除非您先将该转换后的变量存储在另一个变量中。这是因为我在先前的评论中所描述的原因。令人沮丧的是,这个回答被接受了,因为它可能会让人们误以为empty()检查数组是否“空”,而事实上它只是实际操作的一个副作用。 - Timothy Zorn
它能在PHP 7+中工作吗?或者这是修复它的正确方式。 - kantsverma

40

编辑: 我没有意识到他们想要特别检查一个SimpleXMLElement对象是否为空。我在下面保留了旧答案。

更新的答案(SimpleXMLElement):

对于SimpleXMLElement:

如果您的意思是没有属性,则为空:

$obj = simplexml_load_file($url);
if ( !$obj->count() )
{
    // no properties
}

或者

$obj = simplexml_load_file($url);
if ( !(array)$obj )
{
    // empty array
}

如果SimpleXMLElement只有一层深度,而且你所说的“空”实际上是指它只有PHP认为是falsey的属性(或没有属性):

$obj = simplexml_load_file($url);
if ( !array_filter((array)$obj) )
{
    // all properties falsey or no properties at all
}

如果SimpleXMLElement有多个层级,您可以先将其转换为纯数组:

$obj = simplexml_load_file($url);
// `json_decode(json_encode($obj), TRUE)` can be slow because
// you're converting to and from a JSON string.
// I don't know another simple way to do a deep conversion from object to array
$array = json_decode(json_encode($obj), TRUE);
if ( !array_filter($array) )
{
    // empty or all properties falsey
}

旧答案(简单对象):

如果您想检查一个简单对象(类型为stdClass)是否完全为空(没有键/值),可以执行以下操作:

// $obj is type stdClass and we want to check if it's empty
if ( $obj == new stdClass() )
{
    echo "Object is empty"; // JSON: {}
}
else
{
    echo "Object has properties";
}

来源:http://php.net/manual/zh/language.oop5.object-comparison.php

编辑:添加示例


(示例代码请提供)
$one = new stdClass();
$two = (object)array();

var_dump($one == new stdClass()); // TRUE
var_dump($two == new stdClass()); // TRUE
var_dump($one == $two); // TRUE

$two->test = TRUE;
var_dump($two == new stdClass()); // FALSE
var_dump($one == $two); // FALSE

$two->test = FALSE;
var_dump($one == $two); // FALSE

$two->test = NULL;
var_dump($one == $two); // FALSE

$two->test = TRUE;
$one->test = TRUE;
var_dump($one == $two); // TRUE

unset($one->test, $two->test);
var_dump($one == $two); // TRUE

在PHP7.2中无法工作:PHP警告:未捕获的错误:调用未定义的方法stdClass::count() - Juha Untinen
2
@juha-untinen ->count() 的解决方案特别适用于 SimpleXMLElement 实例,而不是 stdClass 实例。 我相信这些在PHP7.2中仍然有效。 - Timothy Zorn

28
您可以将对象转换为数组,并像这样测试其计数:
if(count((array)$obj)) {
   // doStuff
}

16

想象一下,如果对象不是空的,并且相当大,为什么要浪费资源将其转换为数组或序列化它...

这是我在JavaScript中使用的非常简单的解决方案。与将对象转换为数组并检查是否为空或将其编码为JSON的解决方案不同,这个简单的函数在执行简单任务时非常高效。

function emptyObj( $obj ) {
    foreach ( $obj AS $prop ) {
        return FALSE;
    }

    return TRUE;
}
解决方案非常简单:如果对象为空,则根本不会进入foreach循环,并返回true。如果它不为空,它将进入foreach循环并立即返回false,而不是经过整个集合。

解决方案的实现非常简单:如果对象为空,则根本不会进入foreach循环,并返回true。如果它不为空,它将进入foreach循环并立即返回false,而不是经过整个集合。


11

在使用empty()检查对象时,它的行为可能会和预期不同,因为如果对象定义了__isset()方法,那么该方法将被调用。

因此,可以考虑使用count()(如果对象实现了Countable接口)或者使用get_object_vars()函数,例如:

get_object_vars($obj) ? TRUE : FALSE;

7
另一个可能的解决方案是不需要将数据类型转换为array
// test setup
class X { private $p = 1; } // private fields only => empty
$obj = new X;
// $obj->x = 1;


// test wrapped into a function
function object_empty( $obj ){
  foreach( $obj as $x ) return false;
  return true;
}


// inline test
$object_empty = true;
foreach( $obj as $object_empty ){ // value ignored ... 
  $object_empty = false; // ... because we set it false
  break;
}


// test    
var_dump( $object_empty, object_empty( $obj ) );

2

在 PHP 8 版本中

考虑你想要访问一个对象的属性,但不确定该对象本身是否为空,这可能会导致错误。在这种情况下,您可以使用在 PHP 8 中引入的 Nullsafe 运算符,如下所示:

$country = $session?->user?->getAddress()?->country;

2

没有唯一安全的方法来检查一个对象是否为空

PHP的count()首先转换为数组,但是转换可能会产生一个空数组,这取决于对象的实现方式(扩展对象通常受到这些问题的影响)

在您的情况下,您必须使用$obj->count();

http://it.php.net/manual/en/simplexmlelement.count.php

(这不是 PHP 的 count http://www.php.net/count)


1
如果你在PHP中将任何东西转换为(bool),它会立刻告诉你该项是对象、原始类型还是null。使用以下代码:
$obj = simplexml_load_file($url);

if (!(bool)$obj) {
    print "This variable is null, 0 or empty";
} else {
    print "Variable is an object or a primitive type!";
}

1
错误。$x = new \stdClass(); var_dump((bool)$x); 打印出'true'; 在您的情况下,SimpleXml在某些情况下可能会返回false。 - Quamis
正确。new stdClass()是一个有效的对象,这就是为什么它是true。PHP手册说,simplexml_load_file(),“返回一个SimpleXMLElement类的对象,其中包含XML文档中保存的数据的属性,或在失败时返回FALSE。”因此,如果你强制转换(bool)simplexml_load_file(),它将是true(因为函数返回了一个对象),但false(因为函数返回了false)。 - roosevelt

1
根据kenorb的回答,这里有一个适用于具有公共变量的对象的另一种一行代码解决方案。
if (!empty(get_object_vars($myObj))) { ... }

编辑:感谢@mickmackusa在下面的评论中提供的建议-以下是一个更简洁的一行代码,因为它将对象转换为关联数组(具有可访问属性),而在PHP中,空数组是假值。
if (get_object_vars($myObj)) { ... }

编辑2:如果您的对象不是一个真正的对象,get_object_vars()可能会产生警告或提示。在确保变量是一个对象之前,这将检查它是否已被填充:

if (is_object($myObj) && get_object_vars($myObj)) { ... }

再强调一下 - 这适用于具有公共/可访问变量的对象。具有静态、私有或受保护变量的对象将返回false,这可能是意料之外的。请参阅https://www.php.net/manual/en/function.get-object-vars.php

1
!empty() is also checking the existence of the passed in argument -- which is unnecessary. The simper way of doing the same thing is if (get_object_vars($myObj)) { - mickmackusa
1
!empty() 也检查传入参数的存在性 -- 这是不必要的。做相同事情的更简单的方法是 if (get_object_vars($myObj)) { - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接