mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Add ReflectionProperty::getMangledName()
(#18980)
This commit is contained in:
parent
745e81bfd0
commit
d292968f7c
11 changed files with 583 additions and 1 deletions
1
NEWS
1
NEWS
|
@ -255,6 +255,7 @@ PHP NEWS
|
|||
zval for uninitialized typed properties). (nielsdos)
|
||||
. Fixed bug GH-15766 (ReflectionClass::toString() should have better output
|
||||
for enums). (DanielEScherzer)
|
||||
. Added ReflectionProperty::getMangledName() method. (alexandre-daubois)
|
||||
|
||||
- Session:
|
||||
. session_start() throws a ValueError on option argument if not a hashmap
|
||||
|
|
|
@ -467,6 +467,7 @@ PHP 8.5 UPGRADE NOTES
|
|||
ReflectionConstant::getExtensionName() were introduced.
|
||||
. ReflectionConstant::getAttributes() was introduced.
|
||||
RFC: https://wiki.php.net/rfc/attributes-on-constants
|
||||
. ReflectionProperty::getMangledName() was introduced.
|
||||
|
||||
- Sqlite:
|
||||
. Sqlite3Stmt::busy to check if a statement had been fetched
|
||||
|
|
|
@ -5753,6 +5753,21 @@ ZEND_METHOD(ReflectionProperty, getName)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_METHOD(ReflectionProperty, getMangledName)
|
||||
{
|
||||
reflection_object *intern;
|
||||
property_reference *ref;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(ref);
|
||||
if (ref->prop == NULL) {
|
||||
RETURN_STR_COPY(ref->unmangled_name);
|
||||
}
|
||||
|
||||
RETURN_STR_COPY(ref->prop->name);
|
||||
}
|
||||
|
||||
static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
|
||||
{
|
||||
reflection_object *intern;
|
||||
|
|
|
@ -482,6 +482,8 @@ class ReflectionProperty implements Reflector
|
|||
/** @tentative-return-type */
|
||||
public function getName(): string {}
|
||||
|
||||
public function getMangledName(): string {}
|
||||
|
||||
/** @tentative-return-type */
|
||||
public function getValue(?object $object = null): mixed {}
|
||||
|
||||
|
|
6
ext/reflection/php_reflection_arginfo.h
generated
6
ext/reflection/php_reflection_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 7a8d126a96f0115783bd20a9adfc6bdc5ee88fda */
|
||||
* Stub hash: ef9e7f30a29819489e17a9c100f55696d5d164e0 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
|
||||
|
@ -381,6 +381,8 @@ ZEND_END_ARG_INFO()
|
|||
|
||||
#define arginfo_class_ReflectionProperty_getName arginfo_class_ReflectionFunctionAbstract_getName
|
||||
|
||||
#define arginfo_class_ReflectionProperty_getMangledName arginfo_class_ReflectionFunction___toString
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_getValue, 0, 0, IS_MIXED, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, object, IS_OBJECT, 1, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -853,6 +855,7 @@ ZEND_METHOD(ReflectionObject, __construct);
|
|||
ZEND_METHOD(ReflectionProperty, __construct);
|
||||
ZEND_METHOD(ReflectionProperty, __toString);
|
||||
ZEND_METHOD(ReflectionProperty, getName);
|
||||
ZEND_METHOD(ReflectionProperty, getMangledName);
|
||||
ZEND_METHOD(ReflectionProperty, getValue);
|
||||
ZEND_METHOD(ReflectionProperty, setValue);
|
||||
ZEND_METHOD(ReflectionProperty, getRawValue);
|
||||
|
@ -1155,6 +1158,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = {
|
|||
ZEND_ME(ReflectionProperty, __construct, arginfo_class_ReflectionProperty___construct, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, __toString, arginfo_class_ReflectionProperty___toString, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, getName, arginfo_class_ReflectionProperty_getName, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, getMangledName, arginfo_class_ReflectionProperty_getMangledName, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, getValue, arginfo_class_ReflectionProperty_getValue, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, setValue, arginfo_class_ReflectionProperty_setValue, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, getRawValue, arginfo_class_ReflectionProperty_getRawValue, ZEND_ACC_PUBLIC)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
--TEST--
|
||||
Test ReflectionProperty::getMangledName() method
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class TestClass {
|
||||
public $publicProp = 'public';
|
||||
protected $protectedProp = 'protected';
|
||||
private $privateProp = 'private';
|
||||
}
|
||||
|
||||
function testMangledName($class, $property) {
|
||||
$reflection = new ReflectionProperty($class, $property);
|
||||
echo "Property: $property\n";
|
||||
echo "getName(): " . $reflection->getName() . "\n";
|
||||
echo "getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
|
||||
$obj = new $class();
|
||||
$array = (array) $obj;
|
||||
echo "In array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "found" : "not found") . "\n";
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
testMangledName('TestClass', 'publicProp');
|
||||
testMangledName('TestClass', 'protectedProp');
|
||||
testMangledName('TestClass', 'privateProp');
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Property: publicProp
|
||||
getName(): publicProp
|
||||
getMangledName(): publicProp
|
||||
In array cast: found
|
||||
|
||||
Property: protectedProp
|
||||
getName(): protectedProp
|
||||
getMangledName(): %0*%0protectedProp
|
||||
In array cast: found
|
||||
|
||||
Property: privateProp
|
||||
getName(): privateProp
|
||||
getMangledName(): %0TestClass%0privateProp
|
||||
In array cast: found
|
|
@ -0,0 +1,125 @@
|
|||
--TEST--
|
||||
Test ReflectionProperty::getMangledName() with dynamic properties
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "=== Testing stdClass with dynamic properties ===\n";
|
||||
$stdObj = new stdClass();
|
||||
$stdObj->prop1 = 'value1';
|
||||
$stdObj->{'special-name'} = 'special value';
|
||||
$stdObj->{'123numeric'} = 'numeric start';
|
||||
|
||||
function testDynamicProperty($obj, $property, $description) {
|
||||
try {
|
||||
$reflection = new ReflectionProperty($obj, $property);
|
||||
echo "$description:\n";
|
||||
echo " getName(): " . $reflection->getName() . "\n";
|
||||
echo " getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
|
||||
$array = (array) $obj;
|
||||
echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n";
|
||||
echo "\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "$description: EXCEPTION - " . $e->getMessage() . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
testDynamicProperty($stdObj, 'prop1', 'stdClass property prop1');
|
||||
testDynamicProperty($stdObj, 'special-name', 'stdClass property with special name');
|
||||
testDynamicProperty($stdObj, '123numeric', 'stdClass property starting with number');
|
||||
|
||||
echo "=== Testing edge cases ===\n";
|
||||
$numericObj = (object)[true];
|
||||
testDynamicProperty($numericObj, '0', 'Property name as number');
|
||||
|
||||
$nullByteObj = (object)["foo\0" => true];
|
||||
testDynamicProperty($nullByteObj, "foo\0", 'Property name with null byte');
|
||||
|
||||
$invalidObj = (object)["::" => true];
|
||||
testDynamicProperty($invalidObj, '::', 'Invalid property name');
|
||||
|
||||
echo "=== Testing regular class with dynamic properties ===\n";
|
||||
#[AllowDynamicProperties]
|
||||
class TestClass {
|
||||
public $existing = 'existing';
|
||||
}
|
||||
|
||||
$obj = new TestClass();
|
||||
$obj->dynamic = 'dynamic value';
|
||||
$obj->anotherDynamic = 'another dynamic';
|
||||
|
||||
testDynamicProperty($obj, 'dynamic', 'Regular class dynamic property');
|
||||
testDynamicProperty($obj, 'anotherDynamic', 'Regular class another dynamic property');
|
||||
|
||||
$reflection = new ReflectionProperty($obj, 'existing');
|
||||
echo "Regular property:\n";
|
||||
echo " getName(): " . $reflection->getName() . "\n";
|
||||
echo " getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
|
||||
echo "\n=== Testing ReflectionProperty from class vs instance ===\n";
|
||||
try {
|
||||
$reflection = new ReflectionProperty('TestClass', 'dynamic');
|
||||
echo "This should not be reached\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "Expected exception for class-based reflection: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$reflection = new ReflectionProperty($obj, 'dynamic');
|
||||
echo "Instance-based reflection works: " . $reflection->getMangledName() . "\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "Unexpected exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
=== Testing stdClass with dynamic properties ===
|
||||
stdClass property prop1:
|
||||
getName(): prop1
|
||||
getMangledName(): prop1
|
||||
Found in array cast: yes
|
||||
|
||||
stdClass property with special name:
|
||||
getName(): special-name
|
||||
getMangledName(): special-name
|
||||
Found in array cast: yes
|
||||
|
||||
stdClass property starting with number:
|
||||
getName(): 123numeric
|
||||
getMangledName(): 123numeric
|
||||
Found in array cast: yes
|
||||
|
||||
=== Testing edge cases ===
|
||||
Property name as number:
|
||||
getName(): 0
|
||||
getMangledName(): 0
|
||||
Found in array cast: yes
|
||||
|
||||
Property name with null byte:
|
||||
getName(): foo%0
|
||||
getMangledName(): foo%0
|
||||
Found in array cast: yes
|
||||
|
||||
Invalid property name:
|
||||
getName(): ::
|
||||
getMangledName(): ::
|
||||
Found in array cast: yes
|
||||
|
||||
=== Testing regular class with dynamic properties ===
|
||||
Regular class dynamic property:
|
||||
getName(): dynamic
|
||||
getMangledName(): dynamic
|
||||
Found in array cast: yes
|
||||
|
||||
Regular class another dynamic property:
|
||||
getName(): anotherDynamic
|
||||
getMangledName(): anotherDynamic
|
||||
Found in array cast: yes
|
||||
|
||||
Regular property:
|
||||
getName(): existing
|
||||
getMangledName(): existing
|
||||
|
||||
=== Testing ReflectionProperty from class vs instance ===
|
||||
Expected exception for class-based reflection: Property TestClass::$dynamic does not exist
|
||||
Instance-based reflection works: dynamic
|
|
@ -0,0 +1,82 @@
|
|||
--TEST--
|
||||
Test ReflectionProperty::getMangledName() with property hooks
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "=== Testing virtual hooked properties ===\n";
|
||||
|
||||
class Demo {
|
||||
protected string $foo {
|
||||
get => "virtual";
|
||||
}
|
||||
|
||||
public string $bar {
|
||||
get => "hooked getter";
|
||||
set => throw new Exception("Cannot set bar");
|
||||
}
|
||||
|
||||
public string $baz = "backed";
|
||||
}
|
||||
|
||||
$d = new Demo();
|
||||
|
||||
function testHookedProperty($obj, $property, $description) {
|
||||
try {
|
||||
$reflection = new ReflectionProperty($obj, $property);
|
||||
echo "$description:\n";
|
||||
echo " getName(): " . $reflection->getName() . "\n";
|
||||
echo " getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
|
||||
$array = (array) $obj;
|
||||
echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n";
|
||||
echo " Has hooks: " . ($reflection->hasHooks() ? "yes" : "no") . "\n";
|
||||
echo "\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "$description: EXCEPTION - " . $e->getMessage() . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
testHookedProperty($d, 'foo', 'Virtual hooked property (protected)');
|
||||
testHookedProperty($d, 'bar', 'Hooked property with getter/setter (public)');
|
||||
testHookedProperty($d, 'baz', 'Regular backed property');
|
||||
|
||||
echo "=== Object dump ===\n";
|
||||
var_dump($d);
|
||||
|
||||
echo "\n=== Array cast ===\n";
|
||||
var_dump((array)$d);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
=== Testing virtual hooked properties ===
|
||||
Virtual hooked property (protected):
|
||||
getName(): foo
|
||||
getMangledName(): %0*%0foo
|
||||
Found in array cast: no
|
||||
Has hooks: yes
|
||||
|
||||
Hooked property with getter/setter (public):
|
||||
getName(): bar
|
||||
getMangledName(): bar
|
||||
Found in array cast: no
|
||||
Has hooks: yes
|
||||
|
||||
Regular backed property:
|
||||
getName(): baz
|
||||
getMangledName(): baz
|
||||
Found in array cast: yes
|
||||
Has hooks: no
|
||||
|
||||
=== Object dump ===
|
||||
object(Demo)#1 (1) {
|
||||
["bar"]=>
|
||||
uninitialized(string)
|
||||
["baz"]=>
|
||||
string(6) "backed"
|
||||
}
|
||||
|
||||
=== Array cast ===
|
||||
array(1) {
|
||||
["baz"]=>
|
||||
string(6) "backed"
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
--TEST--
|
||||
Test ReflectionProperty::getMangledName() with inheritance
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class ParentClass {
|
||||
public $public = 'parent_public';
|
||||
protected $protected = 'parent_protected';
|
||||
private $private = 'parent_private';
|
||||
private $parentOnly = 'parent_only_private';
|
||||
}
|
||||
|
||||
class ChildClass extends ParentClass {
|
||||
private $private = 'child_private';
|
||||
protected $childProp = 'child_protected';
|
||||
}
|
||||
|
||||
function testProperty($class, $property) {
|
||||
$reflection = new ReflectionProperty($class, $property);
|
||||
$obj = new $class();
|
||||
$array = (array) $obj;
|
||||
|
||||
echo "Class: $class, Property: \$$property\n";
|
||||
echo "Mangled name: '" . $reflection->getMangledName() . "'\n";
|
||||
echo "Key exists in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n";
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
testProperty('ParentClass', 'public');
|
||||
testProperty('ParentClass', 'protected');
|
||||
testProperty('ParentClass', 'private');
|
||||
|
||||
testProperty('ChildClass', 'public');
|
||||
testProperty('ChildClass', 'protected');
|
||||
testProperty('ChildClass', 'childProp');
|
||||
testProperty('ChildClass', 'private');
|
||||
|
||||
echo "Access to parent's private property not in child:\n";
|
||||
|
||||
try {
|
||||
$reflection = new ReflectionProperty('ChildClass', 'parentOnly');
|
||||
echo "ERROR: Should have failed\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "Instance-based creation failed as expected: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$obj = new ChildClass();
|
||||
$reflection = new ReflectionProperty($obj, 'parentOnly');
|
||||
echo "ERROR: Should have failed\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "Object-based creation failed as expected: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Class: ParentClass, Property: $public
|
||||
Mangled name: 'public'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Class: ParentClass, Property: $protected
|
||||
Mangled name: '%0*%0protected'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Class: ParentClass, Property: $private
|
||||
Mangled name: '%0ParentClass%0private'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Class: ChildClass, Property: $public
|
||||
Mangled name: 'public'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Class: ChildClass, Property: $protected
|
||||
Mangled name: '%0*%0protected'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Class: ChildClass, Property: $childProp
|
||||
Mangled name: '%0*%0childProp'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Class: ChildClass, Property: $private
|
||||
Mangled name: '%0ChildClass%0private'
|
||||
Key exists in array cast: yes
|
||||
|
||||
Access to parent's private property not in child:
|
||||
Instance-based creation failed as expected: Property ChildClass::$parentOnly does not exist
|
||||
Object-based creation failed as expected: Property ChildClass::$parentOnly does not exist
|
|
@ -0,0 +1,99 @@
|
|||
--TEST--
|
||||
Test ReflectionProperty::getMangledName() from instance vs class
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[AllowDynamicProperties]
|
||||
class TestClass {
|
||||
public $public = 'public';
|
||||
protected $protected = 'protected';
|
||||
private $private = 'private';
|
||||
}
|
||||
|
||||
$obj = new TestClass();
|
||||
$obj->dynamic = 'dynamic';
|
||||
|
||||
echo "=== Testing ReflectionProperty from CLASS ===\n";
|
||||
|
||||
function testFromClass($property) {
|
||||
try {
|
||||
$reflection = new ReflectionProperty('TestClass', $property);
|
||||
echo "Property $property from class:\n";
|
||||
echo " getName(): " . $reflection->getName() . "\n";
|
||||
echo " getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
echo "\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "Property $property from class: EXCEPTION - " . $e->getMessage() . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
testFromClass('public');
|
||||
testFromClass('protected');
|
||||
testFromClass('private');
|
||||
testFromClass('dynamic');
|
||||
|
||||
echo "=== Testing ReflectionProperty from INSTANCE ===\n";
|
||||
|
||||
function testFromInstance($obj, $property) {
|
||||
try {
|
||||
$reflection = new ReflectionProperty($obj, $property);
|
||||
echo "Property $property from instance:\n";
|
||||
echo " getName(): " . $reflection->getName() . "\n";
|
||||
echo " getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
|
||||
$array = (array) $obj;
|
||||
echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n";
|
||||
echo "\n";
|
||||
} catch (ReflectionException $e) {
|
||||
echo "Property $property from instance: EXCEPTION - " . $e->getMessage() . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
testFromInstance($obj, 'public');
|
||||
testFromInstance($obj, 'protected');
|
||||
testFromInstance($obj, 'private');
|
||||
|
||||
echo "=== Instance array keys ===\n";
|
||||
$array = (array) $obj;
|
||||
foreach (array_keys($array) as $key) {
|
||||
echo "Key: '$key'\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
=== Testing ReflectionProperty from CLASS ===
|
||||
Property public from class:
|
||||
getName(): public
|
||||
getMangledName(): public
|
||||
|
||||
Property protected from class:
|
||||
getName(): protected
|
||||
getMangledName(): %0*%0protected
|
||||
|
||||
Property private from class:
|
||||
getName(): private
|
||||
getMangledName(): %0TestClass%0private
|
||||
|
||||
Property dynamic from class: EXCEPTION - Property TestClass::$dynamic does not exist
|
||||
|
||||
=== Testing ReflectionProperty from INSTANCE ===
|
||||
Property public from instance:
|
||||
getName(): public
|
||||
getMangledName(): public
|
||||
Found in array cast: yes
|
||||
|
||||
Property protected from instance:
|
||||
getName(): protected
|
||||
getMangledName(): %0*%0protected
|
||||
Found in array cast: yes
|
||||
|
||||
Property private from instance:
|
||||
getName(): private
|
||||
getMangledName(): %0TestClass%0private
|
||||
Found in array cast: yes
|
||||
|
||||
=== Instance array keys ===
|
||||
Key: 'public'
|
||||
Key: '%0*%0protected'
|
||||
Key: '%0TestClass%0private'
|
||||
Key: 'dynamic'
|
|
@ -0,0 +1,123 @@
|
|||
--TEST--
|
||||
Test ReflectionProperty::getMangledName() with property overrides and visibility changes
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Parent1 {
|
||||
public $prop = 'parent_public';
|
||||
protected $protectedProp = 'parent_protected';
|
||||
private $privateProp = 'parent_private';
|
||||
}
|
||||
|
||||
class Child1 extends Parent1 {
|
||||
// same visibility
|
||||
public $prop = 'child_public';
|
||||
|
||||
// overridden visibility
|
||||
public $protectedProp = 'child_public_from_protected';
|
||||
}
|
||||
|
||||
class Parent2 {
|
||||
protected $visibilityTest = 'parent_protected';
|
||||
}
|
||||
|
||||
class Child2 extends Parent2 {
|
||||
// overriden visibility
|
||||
public $visibilityTest = 'child_public';
|
||||
}
|
||||
|
||||
function testPropertyOverride($class, $property, $description) {
|
||||
echo "$description:\n";
|
||||
$reflection = new ReflectionProperty($class, $property);
|
||||
echo " Class: $class\n";
|
||||
echo " Property: $property\n";
|
||||
echo " getName(): " . $reflection->getName() . "\n";
|
||||
echo " getMangledName(): " . $reflection->getMangledName() . "\n";
|
||||
echo " Visibility: " . ($reflection->isPublic() ? 'public' : ($reflection->isProtected() ? 'protected' : 'private')) . "\n";
|
||||
|
||||
$obj = new $class();
|
||||
$array = (array) $obj;
|
||||
echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n";
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
testPropertyOverride('Parent1', 'prop', 'Parent public property');
|
||||
testPropertyOverride('Child1', 'prop', 'Child public property (overrides parent public)');
|
||||
|
||||
testPropertyOverride('Parent1', 'protectedProp', 'Parent protected property');
|
||||
testPropertyOverride('Child1', 'protectedProp', 'Child public property (overrides parent protected)');
|
||||
|
||||
testPropertyOverride('Parent2', 'visibilityTest', 'Parent protected property');
|
||||
testPropertyOverride('Child2', 'visibilityTest', 'Child public property (overrides parent protected)');
|
||||
|
||||
testPropertyOverride('Parent1', 'privateProp', 'Parent private property');
|
||||
|
||||
echo "Child1 instance array keys:\n";
|
||||
$child1 = new Child1();
|
||||
$array = (array) $child1;
|
||||
foreach (array_keys($array) as $key) {
|
||||
echo " '$key'\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Parent public property:
|
||||
Class: Parent1
|
||||
Property: prop
|
||||
getName(): prop
|
||||
getMangledName(): prop
|
||||
Visibility: public
|
||||
Found in array cast: yes
|
||||
|
||||
Child public property (overrides parent public):
|
||||
Class: Child1
|
||||
Property: prop
|
||||
getName(): prop
|
||||
getMangledName(): prop
|
||||
Visibility: public
|
||||
Found in array cast: yes
|
||||
|
||||
Parent protected property:
|
||||
Class: Parent1
|
||||
Property: protectedProp
|
||||
getName(): protectedProp
|
||||
getMangledName(): %0*%0protectedProp
|
||||
Visibility: protected
|
||||
Found in array cast: yes
|
||||
|
||||
Child public property (overrides parent protected):
|
||||
Class: Child1
|
||||
Property: protectedProp
|
||||
getName(): protectedProp
|
||||
getMangledName(): protectedProp
|
||||
Visibility: public
|
||||
Found in array cast: yes
|
||||
|
||||
Parent protected property:
|
||||
Class: Parent2
|
||||
Property: visibilityTest
|
||||
getName(): visibilityTest
|
||||
getMangledName(): %0*%0visibilityTest
|
||||
Visibility: protected
|
||||
Found in array cast: yes
|
||||
|
||||
Child public property (overrides parent protected):
|
||||
Class: Child2
|
||||
Property: visibilityTest
|
||||
getName(): visibilityTest
|
||||
getMangledName(): visibilityTest
|
||||
Visibility: public
|
||||
Found in array cast: yes
|
||||
|
||||
Parent private property:
|
||||
Class: Parent1
|
||||
Property: privateProp
|
||||
getName(): privateProp
|
||||
getMangledName(): %0Parent1%0privateProp
|
||||
Visibility: private
|
||||
Found in array cast: yes
|
||||
|
||||
Child1 instance array keys:
|
||||
'prop'
|
||||
'protectedProp'
|
||||
'%0Parent1%0privateProp'
|
Loading…
Add table
Add a link
Reference in a new issue