Take the State of PHP 2026 Survey →

Make reflection setAccessible() no-op View as Markdown

Implemented (PHP 8.1)
Authors
Marco Pivetta
Date
2021-06-13
Version
1.0
Source
wiki.php.net/rfc/make-reflection-setaccessible-no-op

Vote

Make reflection setAccessible() no-op closed
Yes
31
No
0
31 voters
alcaeus Yes 2021-07-01 09:55
asgrim Yes 2021-06-23 16:06
beberlei Yes 2021-06-29 08:36
bwoebi Yes 2021-06-24 15:13
cmb Yes 2021-06-23 17:12
crell Yes 2021-06-23 16:56
daverandom Yes 2021-06-24 22:45
derick Yes 2021-06-23 16:08
galvao Yes 2021-06-25 19:21
jasny Yes 2021-07-01 08:28
kalle Yes 2021-06-23 22:23
kelunik Yes 2021-06-23 18:52
kguest Yes 2021-06-23 17:56
lcobucci Yes 2021-06-23 21:59
marandall Yes 2021-06-23 17:46
nicolasgrekas Yes 2021-07-05 04:28
nikic Yes 2021-06-23 16:47
ocramius Yes 2021-06-23 15:06
petk Yes 2021-07-01 17:03
ralphschindler Yes 2021-06-27 21:14
rasmus Yes 2021-06-26 03:03
reywob Yes 2021-06-23 15:36
sebastian Yes 2021-06-23 15:10
sergey Yes 2021-06-30 09:18
stas Yes 2021-06-30 08:06
svpernova09 Yes 2021-06-23 15:24
tandre Yes 2021-06-23 23:12
theodorejb Yes 2021-06-23 17:04
trowski Yes 2021-06-24 15:13
twosee Yes 2021-06-30 01:44
wyrihaximus Yes 2021-06-27 21:03

Discussions on the mailing list

[RFC] make Reflection*#setAccessible() no-op
by Marco Pivetta · 6 messages
[Vote] make Reflection*#setAccessible() no-op
by Marco Pivetta · 5 messages

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:50 UTC

Introduction

The `ext-reflection` API is designed to inspect static details of a code-base, as well as reading and manipulating runtime state and calling internal details of objects that are otherwise inaccessible.

These methods are most notably:

  • `ReflectionMethod#invoke(): mixed`
  • `ReflectionMethod#invokeArgs(mixed ...$args): mixed`
  • `ReflectionProperty#getValue(object $object): mixed`
  • `ReflectionProperty#setValue(object $object, mixed $value): void`

While breaking encapsulation principles that allow for safe coding practices, these methods are extremely valuable to tools like:

  • mappers
  • serializers
  • debuggers
  • etc.

Infrastructural instrumentation is often required to do things that are in direct conflict with encapsulation itself.

The 4 methods listed above change behavior depending on the only mutable state within the scope of `ext-reflection` classes, which is an “accessible” flag. This “accessibility” flag is steered by:

  • `ReflectionMethod#setAccessible(bool $accessible): void`
  • `ReflectionProperty#setAccessible(bool $accessible): void`

Attempting to use any of the above listed methods without configuring accessibility first will lead to an exception being thrown. For example:

class Foo { private $bar = 'a'; }
 
(new ReflectionProperty(Foo::class, 'bar'))->getValue();

https://3v4l.org/ousrD :

Fatal error: Uncaught ReflectionException: Cannot access non-public property Foo::$bar in <SNIP>

The problem with mutability

By having `ReflectionProperty#setAccessible()` and `ReflectionMethod#setAccessible()`, any consumer of a `ReflectionMethod` or `ReflectionProperty` that is given by a third party must ensure that `#setAccessible()` is called:

function doSomethingWithState(MyObject $o, ReflectionProperty $p) : void
{
    $p->setAccessible(true); // wasteful safety check
 
    doSomethingWith($p->getValue($o));
}

In addition to that, any developer that is intentionally using the reflection API (after having evaluated its trade-off) will have to use this obnoxious syntax in order to use it at its fullest:

$p = new ReflectionProperty(MyClass::class, 'propertyName');
 
$p->setAccessible(true);
 
// now $p is usable

Proposal

This RFC proposes to:

  • make `ReflectionProperty` and `ReflectionMethod` behave as if `#setAccessible(true)` had been called upfront
  • make `ReflectionProperty#setAccessible()` and `ReflectionMethod#setAccessible()` no-op operations, with no side-effects nor state mutation involved

After the RFC is successfully accepted/implemented, the following code should no longer throw, improving therefore the ergonomics around reflection.

class Foo { private $bar = 'a'; }
 
(new ReflectionProperty(Foo::class, 'bar'))->getValue();

Deprecations

In order to ease migration to PHP 8.1, and minimize runtime side-effects, a deprecation is explicitly avoided in this RFC.

Instead, a deprecation should be introduced when a new/separate RFC plans for the removal of `ReflectionProperty#setAccessible()` and `ReflectionMethod#setAccessible()`.

Such RFC will be raised after the release of PHP 8.1, if this RFC is accepted.

Backward Incompatible Changes

Although of minimal concern, it is true that some behavior will change:

  • `ReflectionProperty#getValue()` will no longer throw an exception when used against a protected/private property
  • `ReflectionProperty#setValue()` will no longer throw an exception when used against a protected/private property
  • `ReflectionMethod#invoke()` will no longer throw an exception when used against a protected/private method
  • `ReflectionMethod#invokeArgs()` will no longer throw an exception when used against a protected/private method
  • for extensions developers, `reflection_object->ignore_visibility` no longer exists

Proposed PHP Version(s)

8.1

RFC Impact

To SAPIs

None

To Existing Extensions

None

To Opcache

None

New Constants

None

php.ini Defaults

None

Open Issues

None

Proposed Voting Choices

Accept turning `ReflectionProperty#setAccessible()` and `ReflectionMethod#setAccessible()` into a no-op? (yes/no)

Patches and Tests

https://github.com/php/php-src/pull/5412

Vote

This is a Yes/No vote, requiring a 2/3 majority. Voting started on 2021-06-23 and ends on 2021-07-07.

Vote: Make reflection setAccessible() no-op — Yes: 31 · No: 0 (closed)