178

I understand PHP does not have a pure object variable, but I want to check whether a property is in the given object or class.

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

or

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

In JS, I can write this to check if variable a exists in an object:

if ('a' in ob)

In PHP, can anything like this be done?

Suciu Andrei
  • 118
  • 4
Micah
  • 3,531
  • 7
  • 24
  • 32

10 Answers10

293

property_exists( mixed $class , string $property )

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

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

if (isset($ob->a))

isset() will return false if property is null

Example 1:

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

Example 2:

class Foo
{
   public $bar = null;
}

$foo = new Foo();

var_dump(property_exists($foo, 'bar')); // true
var_dump(isset($foo->bar)); // false
Abel Callejo
  • 10,079
  • 7
  • 50
  • 64
Peter
  • 15,758
  • 7
  • 46
  • 76
  • 14
    Not necessarily, if the property exists, but is not defined isset() will return false. http://us3.php.net/manual/en/types.comparisons.php –  Mar 28 '14 at 05:21
  • isset() can be combined with empty() to check both property **and** value. –  Jul 23 '17 at 22:41
  • 4
    While isset() is the wrong answer, if you are aware of the caveat it is is considerably faster than property_exists() – Nico Westerdale Feb 06 '18 at 20:40
  • is this a situation where `empty()` is a better solution? `!empty($var)` ? – b_dubb Jan 07 '19 at 18:34
  • 1
    @b_dubb no, empty array, 0, false, null, '' all return true by `empty()' – Peter Jan 21 '19 at 20:26
68

To check if the property exists and if it's null too, you can use the function property_exists().

Docs: http://php.net/manual/en/function.property-exists.php

As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.

bool property_exists ( mixed $class , string $property )

Example:

if (property_exists($testObject, $property)) {
    //do something
}
Yevgeniy Afanasyev
  • 27,544
  • 16
  • 134
  • 147
Chiara Perino
  • 770
  • 6
  • 10
  • 8
    This should be marked as the accepted answer since it answers the explicit answer very precise. isset is not useful for testing existence of a property in an object. – Christopher Bonitz Feb 06 '17 at 07:53
14

Neither isset or property_exists work for me.

  • isset returns false if the property exists but is NULL.
  • property_exists returns true if the property is part of the object's class definition, even if it has been unset.

I ended up going with:

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

Example:

    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
  • 141
  • 1
  • 5
  • property_exist + unset property maybe cause buggy behaviour. This seems to be the safest method – Thanh Trung Aug 17 '17 at 00:12
  • array_key_exists() is Deprecated in php 7.4 – Ali_Hr Dec 15 '19 at 08:39
  • The keyword in "Using array_key_exists() on objects is deprecated" is objects. get_object_vars() returns an array, so we're still good. – smariot Dec 16 '19 at 15:20
  • @Ali_Hr Don't know where you saw it in the docs. array_key_exists isn't deprecated in PHP 7.4. – Alexander Behling Aug 04 '20 at 12:57
  • @Thanh Trung Why do you want to unset a class property? property_exists works like expected. If you unset a class property it is internal set to null. Regarding the docs property_exists also returns true if the property is null. So I'm confused what you expected. Also mentionable that property_exist didn't work if the magical method __get is implemented. – Alexander Behling Aug 04 '20 at 12:58
10

Solution

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

To show how this would look in an if statement for more clarity on how this is working.

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

Explanation

The traditional PHP way to check for something's existence is to do:

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

OR for a more class specific way:

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

These are both fine in long form statements but in ternary statements they become unnecessarily cumbersome like so:

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

You can also achieve this with just the ternary operator like so:

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

But... if the value does not exist (is not set) it will raise an E_NOTICE and is not best practise. If the value is null it will not raise the exception.

Therefore ternary operator to the rescue making this a neat little answer:

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

Rob
  • 5,576
  • 4
  • 39
  • 46
4

If you want to know if a property exists in an instance of a class that you have defined, simply combine property_exists() with isset().

public function hasProperty($property)
{
    return property_exists($this, $property) && isset($this->$property);
}
Anthony Rutledge
  • 4,817
  • 31
  • 40
  • 1
    Calling `property_exists($this, $property)` is kind of redundant here, since your code will always have the same result as `isset($this->$property)` alone. – MarthyM Aug 15 '17 at 09:29
  • This is a more complete examination of the facts because `isset()` cannot tell you if a property is a true member of the class definition. I will look up again later to make sure. – Anthony Rutledge Aug 17 '17 at 02:34
  • That is true, the output will be the same for actual class properties. If you have virtual properties with `__get()` and more importantly `__isset()` magic methods, the output will be different in some cases. – MarthyM Aug 17 '17 at 05:58
2

To check if something exits, you can use the PHP function isset() see php.net. This function will check if the variable is set and is not NULL.

Example:

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

If you need to check if a property exists in a class, then you can use the build in function property_exists()

Example:

if (property_exists('class', $property)) {
    //do something
}
Tjoene
  • 355
  • 9
  • 18
2

Using array_key_exists() on objects is Deprecated in php 7.4

Instead either isset() or property_exists() should be used

reference : php.net

Ali_Hr
  • 2,286
  • 2
  • 17
  • 27
0

Just putting my 2 cents here.

Given the following class:

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);
  }
}

the following will happen:

$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

Hope this will help anyone

Victor
  • 11,135
  • 16
  • 65
  • 128
0

Usually I use kind of custom helper

    /**
     * @param Object $object
     * @param string $property as a string with nested properties 'prop1.nesterdProp.deepvalue'
     * @param mixed $default
     * @return mixed
     */
    function getPropertyOrDefault(Object $object, string $property, $default = null)
    {
        $value = $object;
        $path = explode('.', $property);
        foreach ($path as $prop) {
            if (is_object($value) && property_exists($value, $prop)) {
                $value = $value->{$prop};
            } else {
                return $default;
            }
        }
        return $value;
    }

Keep in mind that if property is empty you will get empty value and no default value.

BTW the similar helper works in JS as well.

0

Since php8.0 one can use ?? operator as sugar for isset. Keep in mind that that$foo->bar??<what value you want here> will return <what value you want here> if $foo->bar is not set and $foo->bar otherwise, no matter what value $foo->bar has, posible 0, false, '' or other falsy values