diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 1383c437b6423..64e494200eeac 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -2208,6 +2208,15 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has } } else if (IS_HOOKED_PROPERTY_OFFSET(property_offset)) { zend_function *get = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + + if (has_set_exists == ZEND_PROPERTY_EXISTS) { + if (prop_info->flags & ZEND_ACC_VIRTUAL) { + return true; + } + property_offset = prop_info->offset; + goto try_again; + } + if (!get) { if (prop_info->flags & ZEND_ACC_VIRTUAL) { zend_throw_error(NULL, "Property %s::$%s is write-only", @@ -2219,19 +2228,12 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has } } - if (has_set_exists == ZEND_PROPERTY_EXISTS) { - return 1; - } - zval rv; if (!zend_call_get_hook(prop_info, name, get, zobj, &rv)) { if (EG(exception)) { return 0; } property_offset = prop_info->offset; - if (!ZEND_TYPE_IS_SET(prop_info->type)) { - prop_info = NULL; - } goto try_again; } diff --git a/ext/reflection/tests/property_hooks/ReflectionProperty_isInitialized.phpt b/ext/reflection/tests/property_hooks/ReflectionProperty_isInitialized.phpt new file mode 100644 index 0000000000000..ed1c88b215f12 --- /dev/null +++ b/ext/reflection/tests/property_hooks/ReflectionProperty_isInitialized.phpt @@ -0,0 +1,56 @@ +--TEST-- +ReflectionProperty::isInitialized() on hooked properties +--FILE-- + throw new Exception(); } + public $v2 { set { throw new Exception(); } } + // Backed + public $b1 { get => throw new Exception($this->b1); } + public string $b2 { get => throw new Exception($this->b2); } + public $b3 { set => throw new Exception(); } + public string $b4 { set => throw new Exception(); } +} + +$test = new Test(); +$rc = new ReflectionClass(Test::class); +foreach ($rc->getProperties() as $rp) { + echo $rp->getName(), "\n"; + var_dump($rp->isInitialized($test)); + try { + $rp->setRawValue($test, 42); + } catch (Error $e) {} + var_dump($rp->isInitialized($test)); +} + +?> +--EXPECT-- +p1 +bool(true) +bool(true) +p2 +bool(false) +bool(true) +v1 +bool(true) +bool(true) +v2 +bool(true) +bool(true) +b1 +bool(true) +bool(true) +b2 +bool(false) +bool(true) +b3 +bool(true) +bool(true) +b4 +bool(false) +bool(true)