Check if a property exists on magically set properties
I don't believe there's a way to alter the functionality of property_exists() using magic methods; here's a list of available magic methods in PHP. However, you should be able to alter isset() to use any logic you like.
class test {
private $data = array();
public function __get($key) {
echo "get $key\n";
return array_key_exists($key, $this->data) ? $this->data[$key] : null;
}
public function __set($key, $value) {
echo "set $key = $value\n";
$this->data[$key] = $value;
}
public function __isset($key) {
echo sprintf("isset $key ( returns %b )", array_key_exists($key, $this->data));
return array_key_exists($key, $this->data);
}
}
$test = new test();
$test->x = 42;
isset($test->x); // 1
$test->y = null;
isset($test->y); // 1
This effectively fixes the (annoying) problem with isset and nulls by overriding its functionality through the magic method. Instead of using isset() within __isset() however, we use array_key_exists (which handles nulls as you would expect). Thus __isset() returns the expected result when a null value is set.
This has a downside, namely that the overridden functionality does not produce the same results as default isset() functionality. So, if this object needs to be used transparently with other (perhaps stdClass) objects, then isset() will return true for null values in objects of this class, and false for null values in normal objects.
Depending on your needs then this may or may not be a viable solution. If the above issue is a hindrance, then another option might be to define an interface with a keyIsSet() property, and apply that interface to all objects to be tested. Then use $obj->keyIsSet('key') rather than isset($obj->$key). Not as elegant, but a bit better oo.
![Alain Tiemblo](https://i.stack.imgur.com/wMuZm.png?s=256&g=1)
Alain Tiemblo
I am a geek who subscribed there to have fun. Some people do gaming, some poeple do chatting, and I do code. I can answer a lot of questions, but I prefer strange and challenging problems in PHP, Symfony and/or MySQL. About opensource, I developed twigfiddle.com, a website that provides a small development environment to develop, run, store and access Twig code online, the symfony collection jQuery plugin to handle client-side of Symfony collections, and domajax, a jquery plugin built to make ajax interactions easier and cleaner. You'll find me the most on the php, twig, curl and gd tags.
Updated on June 06, 2022Comments
-
Alain Tiemblo about 2 years
There is a lot of SO questions about the subject, notably this one, but it does not help me.
There is an ambiguity between
property_exists
andisset
so before asking my question, I'm going to pointing it out:property_exists
property_exists checks if an object contains a property without looking at its value, it only looks at its visibility.
So in the following example:
<?php class testA { private $a = null; } class testB extends testA { } $test = new testA(); echo var_dump(property_exists($test, 'a')); // true // parent's private property becomes invisible for its child $test = new testB(); echo var_dump(property_exists($test, 'a')); // false
isset
isset checks if a value exists in a property, considering that is is not set if a value equals
false
andnull
.<?php $var = null; echo var_dump(isset($var)); // false $var = ''; echo var_dump(isset($var)); // true $var = false; echo var_dump(isset($var)); // true $var = 0; echo var_dump(isset($var)); // true $var = '0'; echo var_dump(isset($var)); // true
isset
andproperty_exists
's behaviour on magically added propertiesA property can exist with a
null
value, so I can't use__isset
magic method to know if a property exist or not. I also can't useproperty_exists
as properties are added using magic methods.Here is a sample, but this is just a sample because in my app, properties magically set are stored outside the object.
class test { private $data = array(); public function __get($key) { echo "get $key\n"; return array_key_exists($key, $data) ? $data[$key] : null; } public function __set($key, $value) { echo "set $key = $value\n"; $this->data[$key] = $value; } public function __isset($key) { echo sprintf("isset $key ( returns %b )", isset($this->data[$key])); return isset($this->data[$key]); } } $test = new test(); $test->x = 42; isset($test->x); // 1 $test->y = null; isset($test->y); // 0 property_exists($test, 'y'); // 0
So here is my question :
Is there a magic method or an SPL interface to implement
property_exist
with magically added properties ? -
Alain Tiemblo about 11 yearsAs mentionned,
properties magically set are stored outside the object
. Thanks anyway. -
Alain Tiemblo over 10 yearsSimple, I don't know how I could not have thought about
array_key_exists
before. Thanks. -
Alain Tiemblo over 10 yearsOk now I remember, when I needed this, my properties were stored OUTSIDE the current class (on a parent's one), so it was not possible to use an array to store them, as __get should haven't been called as the property really existed on the final object. Anyway, this is an old question so I leave your answer accpeted.
-
bucabay over 9 years@AlainTiemblo It doesn't matter where you store the properties. property_exists() will return true if a property is set on a parent class. The issue occurs when you don't set the magic property where property_exists() will find it, as it cannot be altered. See my answer to this.