Как проверить, что объект пуст в PHP?

105

Как узнать, пустой объект или нет в PHP.

Ниже приведен код, в котором $objхранятся данные XML. Как я могу проверить, пусто оно или нет?

Мой код:

$obj = simplexml_load_file($url);
песочница
источник
возможный дубликат объекта PHP, содержащего данные XML
Пекка
возможный дубликат Как проверить, пуст ли объект в PHP?
kenorb 04

Ответы:

130

Вы можете преобразовать в массив, а затем проверить, пуст он или нет

$arr = (array)$obj;
if (!$arr) {
    // do stuff
}
Питер Келли
источник
9
Приведение типов у меня не работает, потому что я получаю сообщение об ошибке: Ошибка синтаксического анализа PHP: синтаксическая ошибка, неожиданный '(массив)' (массив) (T_ARRAY_CAST) в ... Я использую версию PHP 5.4.28 и первый вариант с у меня работают две строчки кода.
Коанда
Была такая же ошибка при загрузке плагина WordPress, похоже, они также используют старую версию PHP.
Asaf
4
empty не проверяет, пуст ли массив, что empty($var)эквивалентно (!isset($var) || !$var). Вы можете заменить свои empty($arr)s на !$arrсarray() == FALSE
Тимоти Зорн
2
Причина, по empty((array) $obj)которой не работает PHP 5.4+, не имеет ничего общего с приведением типов в одну строку. Вы получаете ошибку, потому что empty()принимает ссылку на переданные ему переменные, и он не может получить ссылку при приведении типов, если вы сначала не сохраните эту переменную с типом в другой переменной. Это происходит из-за того, что я описал в моем предыдущем комментарии. Довольно неприятно, что это принятый ответ, поскольку он может заставить людей поверить в то, что empty()проверяет, является ли массив «пустым», что не соответствует действительности - это просто побочный эффект того, что он на самом деле делает.
Тимоти Зорн
Будет ли это работать на php 7+, или это правильный способ исправить.
канцверма
32

Изменить : я не понимал, что они хотели специально проверить, пуст ли объект 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 считает ложными (или отсутствие свойств):

$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/en/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 Warning: Uncaught Error: Call to undefined method stdClass::count()
Юха Унтинен
2
@ juha-untinen Решение с ->count()специально предназначено для экземпляров, SimpleXMLElementа не для экземпляров stdClass. Я считаю, что все это все еще работает в PHP7.2.
Тимоти Зорн
21

Вы можете преобразовать свой объект в массив и проверить его количество следующим образом:

if(count((array)$obj)) {
   // doStuff
}
Мохамед23гарби
источник
12

Представьте, что если объект не пустой и довольно большой, зачем вам тратить ресурсы на преобразование его в массив или сериализацию ...

Это очень простое решение, которое я использую в JavaScript. В отличие от упомянутого решения, которое преобразует объект в массив и проверяет, является ли он пустым, или кодирует его в JSON, эта простая функция очень эффективна в отношении используемых ресурсов для выполнения простой задачи.

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

    return TRUE;
}

Решение работает очень просто: он вообще не войдет в цикл foreach, если объект пуст, и он вернется true. Если он не пустой, он войдет в foreachцикл и сразу вернется false, не пройдя через весь набор.

стамат
источник
8

Использование empty()не будет работать как обычно при использовании его с объектом, потому что __isset()вместо него будет вызван метод перегрузки, если он объявлен.

Поэтому вы можете использовать count()(если объект является счетным ).

Или используя get_object_vars(), например,

get_object_vars($obj) ? TRUE : FALSE;
Kenorb
источник
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 count () сначала приводит к массиву, но приведение может создать пустой массив, в зависимости от того, как реализован объект (эти проблемы часто затрагивают объекты расширений)

в вашем случае вы должны использовать $ obj-> count ();

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

(это не счетчик php http://www.php.net/count )


источник
1

Если вы приведете что-либо в PHP как (bool), он сразу скажет вам, является ли элемент объектом, примитивным типом или нулем. Используйте следующий код:

$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 = новый \ stdClass (); var_dump ((bool) $ x); печатает true; В вашем случае simpleXml в некоторых случаях может возвращать false
Quamis
Верный. new stdClass () - допустимый объект, поэтому это правда. В руководстве по PHP написано: simplexml_load_file (): «Возвращает объект класса SimpleXMLElement со свойствами, содержащими данные, хранящиеся в XML-документе, или FALSE в случае ошибки». Итак, если вы приведете (bool) simplexml_load_file (), оно будет истинным (потому что функция вернула объект), но ложным (потому что функция вернула ложь).
Рузвельт
0

Является ли объект «пустым» или нет - это вопрос определения, и поскольку это зависит от природы объекта, который представляет класс, определение этого класса принадлежит классу.

Сам PHP считает каждый экземпляр класса непустым.

class Test { }
$t = new Test();
var_dump(empty($t));

// results in bool(false)

Для «пустого» объекта не может быть общего определения. В приведенном выше примере вы можете возразить, что результат empty()должен быть true, потому что объект не представляет никакого контента. Но как узнать PHP? Некоторые объекты никогда не предназначены для представления контента (например, фабрики мысли), другие всегда представляют значимую ценность (думайте new DateTime()).

Короче говоря, вам нужно будет придумать свои собственные критерии для конкретного объекта и соответственно протестировать их либо извне объекта, либо с помощью самописного isEmpty()метода в объекте.

nem75
источник
0
$array = array_filter($array);
if(!empty($array)) {
    echo "not empty";
}

или

if(count($array) > 0) {
    echo 'Error';
} else {
    echo 'No Error';
}
Мухаммад Тахир
источник
Хотя это может дать ответ на вопрос, всегда полезно включить в ответ текст, объясняющий, что вы делаете. Прочтите, как написать хороший ответ .
Jørgen R
-1

Я использовал json_decode строки в почтовом запросе. У меня ничего из вышеперечисленного не сработало, в конце концов я использовал это:

$post_vals = json_decode($_POST['stuff']);

if(json_encode($post_vals->object) != '{}')
{
    // its not empty
}
Фрэнк Конри
источник