Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,17 @@ PHP 8.6 UPGRADE NOTES
. The mysqli_get_charset() function is now deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_mysqli_get_charset

- Reflection:
. Calling ReflectionProperty::setValue() with an object that is not an
instance of the class on which the property was declared is now deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionpropertysetvalue_and_reflectionpropertysetrawvalue_with_wrong_types
. Calling ReflectionProperty::setRawValue() with an object that is not an
instance of the class on which the property was declared is now deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionpropertysetvalue_and_reflectionpropertysetrawvalue_with_wrong_types
. Calling ReflectionMethod::invoke() or ReflectionMethod::invokeArgs() with
an object and a static method is now deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionmethodinvoke_and_reflectionmethodinvokeargs_with_objects_for_static_methods

- SPL:
. The spl_classes() function is now deprecated, use
ReflectionExtension::getClassNames() instead.
Expand Down
34 changes: 33 additions & 1 deletion ext/reflection/php_reflection.c
Original file line number Diff line number Diff line change
Expand Up @@ -3375,7 +3375,21 @@ static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, bool variadic
* Else, we verify that the given object is an instance of the class.
*/
if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
object = NULL;
if (object) {
zend_string *method_name = get_active_function_or_method_name();
zend_error(
E_DEPRECATED,
"Calling %pS() for static method %pS::%pS() does not need an object parameter",
method_name,
mptr->common.scope->name,
mptr->common.function_name
);
zend_string_release(method_name);
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
object = NULL;
}
obj_ce = mptr->common.scope;
} else {
if (!object) {
Expand Down Expand Up @@ -5919,6 +5933,15 @@ ZEND_METHOD(ReflectionProperty, setValue)
Z_PARAM_ZVAL(value)
ZEND_PARSE_PARAMETERS_END();

if (!instanceof_function(object->ce, intern->ce)) {
zend_string *method_name = get_active_function_or_method_name();
zend_error(E_DEPRECATED, "Calling %pS() with a given object that is not an instance of the class this property was declared in is deprecated", method_name);
zend_string_release(method_name);
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
}

const zend_class_entry *old_scope = EG(fake_scope);
EG(fake_scope) = intern->ce;
object->handlers->write_property(object, ref->unmangled_name, value, ref->cache_slot);
Expand Down Expand Up @@ -6046,6 +6069,15 @@ ZEND_METHOD(ReflectionProperty, setRawValue)
Z_PARAM_ZVAL(value)
} ZEND_PARSE_PARAMETERS_END();

if (!instanceof_function(Z_OBJCE_P(object), intern->ce)) {
zend_string *method_name = get_active_function_or_method_name();
zend_error(E_DEPRECATED, "Calling %pS() with a given object that is not an instance of the class this property was declared in is deprecated", method_name);
zend_string_release(method_name);
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
}

zend_reflection_property_set_raw_value(ref->prop, ref->unmangled_name,
ref->cache_slot, intern->ce, Z_OBJ_P(object), value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ try {
}

?>
--EXPECT--
--EXPECTF--
Non-instance:
string(72) "Given object is not an instance of the class this method was declared in"

Expand All @@ -75,6 +75,8 @@ Exception: Using $this when not in object context
NULL

Private method:

Deprecated: Calling ReflectionMethod::invokeArgs() for static method TestClass::privateMethod() does not need an object parameter in %s on line %d
Called privateMethod()
NULL

Expand Down
2 changes: 2 additions & 0 deletions ext/reflection/tests/ReflectionMethod_invoke_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ NULL
Static method:
ReflectionMethod::invoke() expects at least 1 argument, 0 given
ReflectionMethod::invoke(): Argument #1 ($object) must be of type ?object, true given

Deprecated: Calling ReflectionMethod::invoke() for static method TestClass::staticMethod() does not need an object parameter in %s on line %d
Called staticMethod()
Exception: Using $this when not in object context
NULL
Expand Down
4 changes: 3 additions & 1 deletion ext/reflection/tests/ReflectionMethod_invoke_error1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,16 @@ try {
}

?>
--EXPECT--
--EXPECTF--
invoke() on a non-object:
string(85) "ReflectionMethod::invoke(): Argument #1 ($object) must be of type ?object, true given"

invoke() on a non-instance:
string(72) "Given object is not an instance of the class this method was declared in"

Private method:

Deprecated: Calling ReflectionMethod::invoke() for static method TestClass::privateMethod() does not need an object parameter in %s on line %d
Called privateMethod()
NULL

Expand Down
50 changes: 50 additions & 0 deletions ext/reflection/tests/ReflectionProperty_setRawValue_error.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
--TEST--
Test ReflectionProperty::setRawValue() error cases.
--FILE--
<?php

class Example {
public mixed $nonHooked;

public mixed $hooked {
set(mixed $value) {
throw new Exception("hook should not be called");
$this->hooked = "Not virtual";
}
}
}

#[AllowDynamicProperties]
class AnotherClass {
}

$hookedProp = new ReflectionProperty(Example::class, 'hooked');
$nonHookedProp = new ReflectionProperty(Example::class, 'nonHooked');

$instance = new Example();
$hookedProp->setRawValue($instance, "value1");
$nonHookedProp->setRawValue($instance, "value2");
var_dump($instance);

$other = new AnotherClass();
$hookedProp->setRawValue($other, "value1");
$nonHookedProp->setRawValue($other, "value2");
var_dump($other);
?>
--EXPECTF--
object(Example)#%d (2) {
["nonHooked"]=>
string(6) "value2"
["hooked"]=>
string(6) "value1"
}

Deprecated: Calling ReflectionProperty::setRawValue() with a given object that is not an instance of the class this property was declared in is deprecated in %s on line %d

Deprecated: Calling ReflectionProperty::setRawValue() with a given object that is not an instance of the class this property was declared in is deprecated in %s on line %d
object(AnotherClass)#%d (2) {
["hooked"]=>
string(6) "value1"
["nonHooked"]=>
string(6) "value2"
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ $propInfo = new ReflectionProperty('TestClass', 'pub2');
var_dump($propInfo->setValue($instanceWithNoProperties, "NewValue"));
var_dump($instanceWithNoProperties->pub2);
?>
--EXPECT--
--EXPECTF--
Protected property:
string(8) "NewValue"


Instance without property:

Deprecated: Calling ReflectionProperty::setValue() with a given object that is not an instance of the class this property was declared in is deprecated in %s on line %d
NULL
string(8) "NewValue"
Loading