PHP проверяет, существует ли свойство в объекте или классе

159

Я понимаю, что PHP не имеет чисто объектной переменной, но я хочу проверить, находится ли свойство в данном объекте или классе.

$ob = (object) array('a' => 1, 'b' => 12); 

или

$ob = new stdClass;
$ob->a = 1;
$ob->b = 2;

В JS я могу написать это, чтобы проверить, aсуществует ли переменная в объекте:

if ('a' in ob)

В PHP можно сделать что-нибудь подобное?

Большое спасибо за ваш совет.

Михей
источник
2
Просто упомянув ... когда мы делаем ООП, мы говорим, что свойство не переменное, как мы говорим метод, а не функция.
Кристофер Бонитц

Ответы:

254

property_exists (смешанный класс $, строка $ свойство)

if (property_exists($ob, 'a')) 

isset (mixed $ var [, mixed $ ...])

if (isset($ob->a))

isset () вернет false, если свойство равно нулю

Пример 1:

$ob->a = null
var_dump(isset($ob->a)); // false

Пример 2:

class Foo
{
   public $bar = null;
}

$foo = new Foo();

var_dump(property_exists($foo, 'bar')); // true
var_dump(isset($foo->bar)); // false
Питер
источник
12
Не обязательно, если свойство существует, но не определено, isset () вернет false. us3.php.net/manual/en/types.comparisons.php
Митчелл
isset () можно комбинировать с empty () для проверки как свойства, так и значения.
4
Хотя isset () является неправильным ответом, если вы знаете о предупреждении, это значительно быстрее, чем property_exists ()
Нико Вестердейл
это ситуация, где empty()лучшее решение? !empty($var)?
b_dubb
1
@b_dubb нет, пустой массив, 0, ложь, ноль, '' все возвращают истину с помощью `empty () '
Питер
61

Чтобы проверить, существует ли свойство и имеет ли оно значение null, вы можете использовать функцию property_exists().

Документы: http://php.net/manual/en/function.property-exists.php

В отличие от isset (), property_exists () возвращает TRUE, даже если свойство имеет значение NULL.

bool property_exists (смешанный класс $, строка $ свойство)

Пример:

if (property_exists($testObject, $property)) {
    //do something
}
Кьяра Перино
источник
7
Это должно быть помечено как принятый ответ, так как он дает точный ответ. isset не полезен для проверки существования свойства в объекте.
Кристофер Бонитц
11

Ни isset, ни property_exists не работают для меня.

  • isset возвращает false, если свойство существует, но имеет значение NULL.
  • property_exists возвращает true, если свойство является частью определения класса объекта, даже если оно не установлено.

Я закончил тем, что пошел с:

    $exists = array_key_exists($property, get_object_vars($obj));

Пример:

    class Foo {
        public $bar;

        function __construct() {
            $property = 'bar';

            isset($this->$property); // FALSE
            property_exists($this, $property); // TRUE
            array_key_exists($property, get_object_vars($this)); // TRUE

            unset($this->$property);

            isset($this->$property); // FALSE
            property_exists($this, $property); // TRUE
            array_key_exists($property, get_object_vars($this)); // FALSE

            $this->$property = 'baz';

            isset($this->$property); // TRUE
            property_exists($this, $property); // TRUE
            array_key_exists($property, get_object_vars($this));  // TRUE
        }
    }
smariot
источник
property_exist + unset свойство может вызывать некорректное поведение. Это, кажется, самый безопасный метод
Тхан Чунг
array_key_exists () устарела в php 7.4
Ali_Hr
Ключевое слово в "Использование array_key_exists () для объектов устарело" - это объекты. get_object_vars () возвращает массив, поэтому мы все еще в порядке.
Смариот
7

Решение

echo $person->middleName ?? 'Person does not have a middle name';

Чтобы показать, как это будет выглядеть в операторе if, для большей ясности о том, как это работает.

if($person->middleName ?? false) {
    echo $person->middleName;
} else {
    echo 'Person does not have a middle name';
}

объяснение

Традиционный способ проверки существования чего-либо на PHP заключается в следующем:

if(isset($person->middleName)) {
    echo $person->middleName;
} else {
    echo 'Person does not have a middle name';
}

ИЛИ для более специфичного для класса способа:

if(property_exists($person, 'middleName')) {
    echo $person->middleName;
} else {
    echo 'Person does not have a middle name';
}

Они оба хороши в длинных выражениях, но в троичных выражениях они становятся излишне громоздкими, например:

isset($person->middleName) ? echo $person->middleName : echo 'Person does not have a middle name';

Вы также можете достичь этого только с помощью троичного оператора, например:

echo $person->middleName ?: 'Person does not have a middle name';

Но ... если значение не существует (не установлено), оно вызовет E_NOTICEи не является лучшей практикой. Если значение равно, nullоно не вызовет исключения.

Поэтому троичный оператор на помощь делает этот аккуратный маленький ответ:

echo $person->middleName ?? 'Person does not have a middle name';

обкрадывать
источник
Отличное объяснение!
DasBen
4

Если вы хотите узнать, существует ли свойство в экземпляре класса, который вы определили, просто объедините property_exists()с isset().

public function hasProperty($property)
{
    return property_exists($this, $property) && isset($this->$property);
}
Энтони Ратледж
источник
1
Вызов property_exists($this, $property)здесь отчасти избыточен, поскольку ваш код всегда будет иметь тот же результат, что и isset($this->$property)один.
MarthyM
Это более полное исследование фактов, потому что isset()не может сказать вам, является ли свойство истинным членом определения класса. Я посмотрю еще раз позже, чтобы убедиться.
Энтони Ратледж
Это правда, выходные данные будут одинаковыми для реальных свойств класса. Если у вас есть виртуальные свойства __get()и, что более важно, __isset()магические методы, результат будет отличаться в некоторых случаях.
MarthyM
1

Чтобы проверить, завершается ли что-то, вы можете использовать функцию PHP isset (), см. Php.net . Эта функция проверит, установлена ​​ли переменная и не имеет ли значение NULL.

Пример:

if(isset($obj->a))
{ 
  //do something
}

Если вам нужно проверить, существует ли свойство в классе, вы можете использовать встроенную функцию property_exists ()

Пример:

if (property_exists('class', $property)) {
    //do something
}
Tjoene
источник
1

Использование array_key_exists () для объектов устарело в php 7.4

Вместо этого следует использовать либо isset (), либо property_exists ()

ссылка: php.net

Ali_Hr
источник
0

Просто положил мои 2 цента здесь.

Учитывая следующий класс:

class Foo
{
  private $data;

  public function __construct(array $data)
  {
    $this->data = $data;
  }

  public function __get($name)
  {
    return $data[$name];
  }

  public function __isset($name)
  {
    return array_key_exists($name, $this->data);
  }
}

произойдет следующее:

$foo = new Foo(['key' => 'value', 'bar' => null]);

var_dump(property_exists($foo, 'key'));  // false
var_dump(isset($foo->key));  // true
var_dump(property_exists($foo, 'bar'));  // false
var_dump(isset($foo->bar));  // true, although $data['bar'] == null

Надеюсь, это поможет кому-нибудь

Виктор
источник