<?php
class Box {
public string $label {
get => strtoupper($this->label);
set (string $v) { $this->label = $v; }
}
public function __construct() { $this->label = 'hi'; }
}
$o = new Box();
var_export(isset($o->label));
echo "\n";
var_export(empty($o->label));
echo "\n";
Category
languageProblem
PHP 8.4 property hooks:
isset($obj->prop)andempty($obj->prop)on a hooked property must run the get hook (or Zend-equivalent logic) before testing definedness, not only read raw backing storage. This compiler has get/set hook dispatch on fetch/store (lib/VM.phpfetchPropertyWithHooks) butobjectPropertyIsSet()may disagree with Zend when the backing field is unset and only the get hook supplies a value.Repro sketch:
test/repro-maintainer/property_hook_isset.php.php-src reference
Zend/zend_property_hooks.c—isset/emptyon hooked propertiesZend/zend_object_handlers.c—zend_std_has_propertyRepro
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro-maintainer/property_hook_isset.php' php test/repro-maintainer/property_hook_isset.phpisset($o->label)after constructtrueempty($o->label)for non-empty hook valuefalseAdd a get-only case (no set hook) per #4687 when that lands.
Scope
lib/VM.php—objectPropertyIsSet,empty()lowering on property fetcheslib/SourcePreprocessor/PropertyHooks.php— hook method nameslib/JIT/PropertyHookDispatch.php— JIT isset/empty (phase 2 OK to defer)test/compliance/cases/language/property_hook_isset_empty.phptDone when
issetfollows get hook (Language: property hooks — get-only virtual properties without set hook (zend_property_hooks.c) #4687)./script/ci-fast.sh --filter property_hook_issetgreenLinks