[PHP-DEV] [RFC] isReadable/isWriteable property reflection

In other news, Ilija and I said a year ago that we'd take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

--
  Larry Garfield
  larry@garfieldtech.com

Hi

Am 2025-11-06 00:24, schrieb Larry Garfield:

In other news, Ilija and I said a year ago that we'd take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

I dislike implicitly “scope-dependent” functions, since they effectively act like magic. This probably makes it harder to understand for humans and static analysis tools alike. I would therefore suggest making the `$scope` parameter required. A user can just pass `static::class` themselves and static analysis tools can use `class-string|null` instead of `class-string|"static"|null` as their expected parameter type.

As for the magic method logic: I would suggest to ignore the presence of __get() and __set(). This more closely aligns with the direction PHP goes towards and is also easy to work around by checking with `method_exists()` whether any such a method exists - the reverse is not true.

Best regards
Tim Düsterhus

On Fri, Nov 7, 2025, at 5:03 AM, Tim Düsterhus wrote:

Hi

Am 2025-11-06 00:24, schrieb Larry Garfield:

In other news, Ilija and I said a year ago that we'd take a swing at
adding isReadable/isWriteable methods to ReflectionProperty. Took a
while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

I dislike implicitly “scope-dependent” functions, since they effectively
act like magic. This probably makes it harder to understand for humans
and static analysis tools alike. I would therefore suggest making the
`$scope` parameter required. A user can just pass `static::class`
themselves and static analysis tools can use `class-string|null` instead
of `class-string|"static"|null` as their expected parameter type.

Given that the 90% or more case is likely to be "from my current context", making that the default seems the most ergonomic. (The counter argument, I suppose, is that this is hardly going to be a super-common routine to call so ergonomics don't matter.)

stack-inspection isn't new. `Closure::getCurrent()` is the most recent example, so we don't think it's especially problematic.

If there's a preference for avoiding magic strings, it would be easy enough to use an enum instead. Something like:

enum CallerScope {
  case Caller;
  case Global;
}

function isReadable(string|CallerScope $scope = CallerScope::Caller, ?object $objecg = null) { ... }

`Caller` would still do the same stack inspection, but it makes the type more tightly controlled and eliminates a nullable.

As for the magic method logic: I would suggest to ignore the presence of
__get() and __set(). This more closely aligns with the direction PHP
goes towards and is also easy to work around by checking with
`method_exists()` whether any such a method exists - the reverse is not
true.

thumbs-up.gif

--Larry Garfield

Hi

On 11/7/25 20:12, Larry Garfield wrote:

(The counter argument, I suppose, is that this is hardly going to be a super-common routine to call so ergonomics don't matter.)

Yes. I expect this to mostly be useful deep within frameworks or specialized libraries. The type of code where these functions are likely to be used are very likely to be functions with an above-average complexity and having explicit code there will help keep the complexity low. Also it's not like `static::class` is particularly complicated to use.

One issue I'm seeing with the “magic context” logic is that the code will suddenly break when the call to `->isReadable()` is moved into a helper function. Particularly when you consider the __get() use case that I mentioned below: Folks that are interested in wanting to learn whether there's a property that is actually readable *or* a magic getter might want to put this combined logic into a helper - and then the implicit scope will no longer work.

stack-inspection isn't new. `Closure::getCurrent()` is the most recent example, so we don't think it's especially problematic.

The difference is that `Closure::getCurrent()` is a single-purpose function that is explicitly defined to operate on the current scope. It specifically throws an Error when misused. `->isReadable()` OTOH will silently misbehave.

AFAICT it would also be the first reflection function that has dynamic behavior.

If there's a preference for avoiding magic strings, it would be easy enough to use an enum instead. Something like:

My issue is not primarily with the “magic string”, but with the quite significant behavioral difference depending on the parameter value.

Best regards
Tim Düsterhus

Le jeu. 6 nov. 2025 à 00:28, Larry Garfield <larry@garfieldtech.com> a écrit :

In other news, Ilija and I said a year ago that we’d take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

https://wiki.php.net/rfc/isreadable-iswriteable

Thanks for this.

I also think the auto-scope is a good idea. You state that 90% of use cases will need this but my experience doesn’t back this claim. The only cases where I had to check for read/writeable were out of the local scope, so I’d say 100% of my experience goes against that 90% number :wink: Joke aside, it’d be just fine to let ppl be explicit. That’s better than “oops I forgot to give the correct scope” bugs.

About magic methods, one unsets a property only to have __get/__set called. Existing code works with this assumption. This means we have to return true IMHO. Magic methods are just generic hooks also. Which means they should behave the same.

Nicolas

Sorry, typo:

I also think the auto-scope is a not good idea

Le jeu. 4 déc. 2025 à 15:05, Nicolas Grekas <nicolas.grekas+php@gmail.com> a écrit :

Le jeu. 6 nov. 2025 à 00:28, Larry Garfield <larry@garfieldtech.com> a écrit :

In other news, Ilija and I said a year ago that we’d take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

https://wiki.php.net/rfc/isreadable-iswriteable

Thanks for this.

I also think the auto-scope is a good idea. You state that 90% of use cases will need this but my experience doesn’t back this claim. The only cases where I had to check for read/writeable were out of the local scope, so I’d say 100% of my experience goes against that 90% number :wink: Joke aside, it’d be just fine to let ppl be explicit. That’s better than “oops I forgot to give the correct scope” bugs.

About magic methods, one unsets a property only to have __get/__set called. Existing code works with this assumption. This means we have to return true IMHO. Magic methods are just generic hooks also. Which means they should behave the same.

Nicolas

On Thu, Dec 4, 2025, at 8:05 AM, Nicolas Grekas wrote:

Le jeu. 6 nov. 2025 à 00:28, Larry Garfield <larry@garfieldtech.com> a écrit :

In other news, Ilija and I said a year ago that we'd take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

Thanks for this.
I also think the auto-scope is [NOT] a good idea. You state that 90% of use
cases will need this but my experience doesn't back this claim. The
only cases where I had to check for read/writeable were out of the
local scope, so I'd say 100% of my experience goes against that 90%
number :wink: Joke aside, it'd be just fine to let ppl be explicit. That's
better than "oops I forgot to give the correct scope" bugs.

About magic methods, one unsets a property only to have __get/__set
called. Existing code works with this assumption. This means we have to
return true IMHO. Magic methods are just generic hooks also. Which
means they should behave the same.

Nicolas

Well, the only people who seem to have an opinion don't like "static", so we've removed it. RFC updated.

As for __get/__set, that's so far one vote for ignore (Tim), and one for always-true (Nicolas). Not a consensus. :slight_smile:

Nicolas, can you clarify with an example if/how ignore would break things?

I think once we settle that question and the cooldown passes we're ready for a vote, though at this point that means January.

--Larry Garfield

Le jeu. 4 déc. 2025 à 17:39, Larry Garfield <larry@garfieldtech.com> a écrit :

On Thu, Dec 4, 2025, at 8:05 AM, Nicolas Grekas wrote:

Le jeu. 6 nov. 2025 à 00:28, Larry Garfield <larry@garfieldtech.com> a écrit :

In other news, Ilija and I said a year ago that we’d take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

https://wiki.php.net/rfc/isreadable-iswriteable

Thanks for this.
I also think the auto-scope is [NOT] a good idea. You state that 90% of use
cases will need this but my experience doesn’t back this claim. The
only cases where I had to check for read/writeable were out of the
local scope, so I’d say 100% of my experience goes against that 90%
number :wink: Joke aside, it’d be just fine to let ppl be explicit. That’s
better than “oops I forgot to give the correct scope” bugs.

About magic methods, one unsets a property only to have __get/__set
called. Existing code works with this assumption. This means we have to
return true IMHO. Magic methods are just generic hooks also. Which
means they should behave the same.

Nicolas

Well, the only people who seem to have an opinion don’t like “static”, so we’ve removed it. RFC updated.

As for __get/__set, that’s so far one vote for ignore (Tim), and one for always-true (Nicolas). Not a consensus. :slight_smile:

Nicolas, can you clarify with an example if/how ignore would break things?

I think once we settle that question and the cooldown passes we’re ready for a vote, though at this point that means January.

I can try to build a synthetic example but the gist is:
A class that starts with only properties and no __get() should be able to move to a __get()-based hooking in a later version without breaking code that uses isReadable().
That on its own should be enough to settle the desired behavior :slight_smile:

On Thu, Dec 4, 2025, at 10:47 AM, Nicolas Grekas wrote:

Le jeu. 4 déc. 2025 à 17:39, Larry Garfield <larry@garfieldtech.com> a écrit :

On Thu, Dec 4, 2025, at 8:05 AM, Nicolas Grekas wrote:
> Le jeu. 6 nov. 2025 à 00:28, Larry Garfield <larry@garfieldtech.com> a écrit :
>> In other news, Ilija and I said a year ago that we'd take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:
>>
>> PHP: rfc:isreadable-iswriteable
>>
>
>
> Thanks for this.
> I also think the auto-scope is [NOT] a good idea. You state that 90% of use
> cases will need this but my experience doesn't back this claim. The
> only cases where I had to check for read/writeable were out of the
> local scope, so I'd say 100% of my experience goes against that 90%
> number :wink: Joke aside, it'd be just fine to let ppl be explicit. That's
> better than "oops I forgot to give the correct scope" bugs.
>
> About magic methods, one unsets a property only to have __get/__set
> called. Existing code works with this assumption. This means we have to
> return true IMHO. Magic methods are just generic hooks also. Which
> means they should behave the same.
>
> Nicolas

Well, the only people who seem to have an opinion don't like "static", so we've removed it. RFC updated.

As for __get/__set, that's so far one vote for ignore (Tim), and one for always-true (Nicolas). Not a consensus. :slight_smile:

Nicolas, can you clarify with an example if/how ignore would break things?

I think once we settle that question and the cooldown passes we're ready for a vote, though at this point that means January.

I can try to build a synthetic example but the gist is:
A class that starts with only properties and no __get() should be able
to move to a __get()-based hooking in a later version without breaking
code that uses isReadable().
That on its own should be enough to settle the desired behavior :slight_smile:

So you want to be able to transition from:

class Foo
{
  public private(set) string $name;
}

To

class Foo
{
  private array $vals = ;

  public function __get(string $name)
  {
    return $this->vals[$name] ?? throw new Exception();
  }
}

Is that right? Because both approaches would result in changes in some situations there.

If __get is ignored and the value is set, then a global isReadable check will go from true to false in that transition.

If __get always returns true and the value is still uninitialized, a global isReadable check will go from false to true in that transition.

Either way, that's not a fully safe transition to make.

--Larry Garfield

Le jeu. 4 déc. 2025 à 18:03, Larry Garfield <larry@garfieldtech.com> a écrit :

On Thu, Dec 4, 2025, at 10:47 AM, Nicolas Grekas wrote:

Le jeu. 4 déc. 2025 à 17:39, Larry Garfield <larry@garfieldtech.com> a écrit :

On Thu, Dec 4, 2025, at 8:05 AM, Nicolas Grekas wrote:

Le jeu. 6 nov. 2025 à 00:28, Larry Garfield <larry@garfieldtech.com> a écrit :

In other news, Ilija and I said a year ago that we’d take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

https://wiki.php.net/rfc/isreadable-iswriteable

Thanks for this.
I also think the auto-scope is [NOT] a good idea. You state that 90% of use
cases will need this but my experience doesn’t back this claim. The
only cases where I had to check for read/writeable were out of the
local scope, so I’d say 100% of my experience goes against that 90%
number :wink: Joke aside, it’d be just fine to let ppl be explicit. That’s
better than “oops I forgot to give the correct scope” bugs.

About magic methods, one unsets a property only to have __get/__set
called. Existing code works with this assumption. This means we have to
return true IMHO. Magic methods are just generic hooks also. Which
means they should behave the same.

Nicolas

Well, the only people who seem to have an opinion don’t like “static”, so we’ve removed it. RFC updated.

As for __get/__set, that’s so far one vote for ignore (Tim), and one for always-true (Nicolas). Not a consensus. :slight_smile:

Nicolas, can you clarify with an example if/how ignore would break things?

I think once we settle that question and the cooldown passes we’re ready for a vote, though at this point that means January.

I can try to build a synthetic example but the gist is:
A class that starts with only properties and no __get() should be able
to move to a __get()-based hooking in a later version without breaking
code that uses isReadable().
That on its own should be enough to settle the desired behavior :slight_smile:

So you want to be able to transition from:

class Foo
{
public private(set) string $name;
}

To

class Foo
{
private array $vals = ;

public function __get(string $name)
{
return $this->vals[$name] ?? throw new Exception();
}
}

Is that right? Because both approaches would result in changes in some situations there.

If __get is ignored and the value is set, then a global isReadable check will go from true to false in that transition.

If __get always returns true and the value is still uninitialized, a global isReadable check will go from false to true in that transition.

Either way, that’s not a fully safe transition to make.

–Larry Garfield

Nah, I’m thinking about a scenario very close to what you talk about in the RFC: unset + __get

From:
class Foo
{
public int $abc;

public function __construct()
{
$this->abc = stuff();
}
}

To:

class Foo
{
public int $abc;

public function __construct()
{
unset($this->abc);
}

public function __get($name)
{
if (‘abc’ === $name) {
return $this->abc = stuff();
}
}

}

Hey Larry,

On 6.11.2025 00:24:52, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we'd take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

Have you considered returning false on isReadable() and isWritable() for methods, whose only statement is throwing? I.e. when a getter or setter unconditionally throws without any other statements present, they are not marked as readable or writable.

Otherwise this essentially "punishes" providing better exceptions in a getter or setter, and serves also cases where the LSP inheritance forces presence of a getter/setter, but still shall not be allowed on the specific instance.

Thanks,
Bob

On Thu, Dec 4, 2025, at 2:54 PM, Bob Weinand wrote:

Hey Larry,

On 6.11.2025 00:24:52, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we'd take a swing at adding isReadable/isWriteable methods to ReflectionProperty. Took a while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

Have you considered returning false on isReadable() and isWritable() for
methods, whose only statement is throwing? I.e. when a getter or setter
unconditionally throws without any other statements present, they are
not marked as readable or writable.

Otherwise this essentially "punishes" providing better exceptions in a
getter or setter, and serves also cases where the LSP inheritance forces
presence of a getter/setter, but still shall not be allowed on the
specific instance.

Thanks,
Bob

Hi Bob.

We've discussed it privately, and feel it would be an unprecedented amount of magic behavior to introduce in what is otherwise a fairly small utility RFC. Nowhere else does PHP do that kind of deep runtime introspection, and it's a rabbit hole much larger than we want to tackle. It's also a non-trivial problem to solve. For `throw new Exception();`, the opcodes look something like `V1 = NEW; DO_FCALL; THROW V1;.` That's fairly straight-forward. But what about:

* throw new Exception(getErrorMessage());
* throw new Exception(cond() ? 'Message 1' : 'Message 2');
* $message = getErrorMessage(); throw new Exception($message);
* if (cond()) { $message = 'Message 1'; } else { $message = 'Message 2'; } throw new Exception($message);

It's very hard to draw an arbitrary line to decide what is and what isn't allowed. Handling these cases correctly would require a significant amount of complexity, and would still be incomplete. If making small, seemingly benign changes can break the exception detection, that's arguably worse than no detection at all.

For now we'd rather just avoid that rabbit hole.

--Larry Garfield

On Wed, Nov 5, 2025, at 5:24 PM, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we'd take a swing at
adding isReadable/isWriteable methods to ReflectionProperty. Took a
while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

A few updates based on the discussion here:

* We now account for static properties. (What a concept.)
* The `static` magic string is gone.
* We have decided on an approach for magic methods. The updated RFC text explains it in more detail, but in short, "if __isset(), then use that to determine readable. Otherwise, __get() implies readable. __set() implies writeable." That should handle the use cases Nicolas was interested in.

We consider the RFC feature complete at this point. Baring any further substantive discussion, expect a vote in January after the blackout period ends.

--Larry Garfield

Hi

Am 2025-12-17 16:26, schrieb Larry Garfield:

* We have decided on an approach for magic methods. The updated RFC text explains it in more detail, but in short, "if __isset(), then use that to determine readable. Otherwise, __get() implies readable. __set() implies writeable." That should handle the use cases Nicolas was interested in.

That works for me. I didn't feel particularly strongly either way.

We consider the RFC feature complete at this point. Baring any further substantive discussion, expect a vote in January after the blackout period ends.

I don't have further comments about the semantics themselves, but have one further clarification question:

The property has not been unset(). If it has, follow the same __isset check as above

Should this read “the same __get check” instead?

And one note with regard to process: Don't forget to add a link to the discussion (php.internals: [RFC] isReadable/isWriteable property reflection) to the RFC.

Best regards
Tim Düsterhus

On Wed, Dec 17, 2025, at 12:02 PM, Tim Düsterhus wrote:

Hi

Am 2025-12-17 16:26, schrieb Larry Garfield:

* We have decided on an approach for magic methods. The updated RFC
text explains it in more detail, but in short, "if __isset(), then use
that to determine readable. Otherwise, __get() implies readable.
__set() implies writeable." That should handle the use cases Nicolas
was interested in.

That works for me. I didn't feel particularly strongly either way.

We consider the RFC feature complete at this point. Baring any further
substantive discussion, expect a vote in January after the blackout
period ends.

I don't have further comments about the semantics themselves, but have
one further clarification question:

The property has not been unset(). If it has, follow the same __isset
check as above

Should this read “the same __get check” instead?

Hm, yes, you are correct. Updated.

And one note with regard to process: Don't forget to add a link to the
discussion (php.internals: [RFC] isReadable/isWriteable property reflection) to the RFC.

Added.

Oh, and one other note: It turns out that in English, both "writeable" and "writable" are nominally valid. The latter seems more common (and my spellchecker only recognizing the latter), so we've standardized on the non-E version throughout the RFC. (The code already was.)

--Larry Garfield

Hi

Am 2025-12-17 20:48, schrieb Larry Garfield:

Oh, and one other note: It turns out that in English, both "writeable" and "writable" are nominally valid. The latter seems more common (and my spellchecker only recognizing the latter), so we've standardized on the non-E version throughout the RFC. (The code already was.)

As a non-native speaker, I confirm that “writable” without the “e” is what looks more familiar to me. It's also consistent with PHP: is_writable - Manual (although that one has an alias PHP: is_writeable - Manual - but since the one with the “e” is the alias, it is the less preferable variant).

Best regards
Tim Düsterhus

Le mer. 17 déc. 2025 à 16:29, Larry Garfield <larry@garfieldtech.com> a écrit :

On Wed, Nov 5, 2025, at 5:24 PM, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we’d take a swing at
adding isReadable/isWriteable methods to ReflectionProperty. Took a
while, but here we are. A strangely small RFC from us:

https://wiki.php.net/rfc/isreadable-iswriteable

A few updates based on the discussion here:

  • We now account for static properties. (What a concept.)
  • The static magic string is gone.
  • We have decided on an approach for magic methods. The updated RFC text explains it in more detail, but in short, “if __isset(), then use that to determine readable. Otherwise, __get() implies readable. __set() implies writeable.” That should handle the use cases Nicolas was interested in.

We consider the RFC feature complete at this point. Baring any further substantive discussion, expect a vote in January after the blackout period ends.

Hi, thanks for the update!
I read the updated description and that looks great to me, thanks.

Nicolas

On Wed, Nov 5, 2025, at 5:24 PM, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we'd take a swing at
adding isReadable/isWriteable methods to ReflectionProperty. Took a
while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

Hi folks.

The holiday blackout period is over, and there's nothing else really to discuss on this PR, so consider this an Intent to Vote notice for the isReadable RFC.

I'll call the vote later this week, baring any new serious constructive feedback.

--Larry Garfield

Le 13 janv. 2026 à 22:30, Larry Garfield larry@garfieldtech.com a écrit :

On Wed, Nov 5, 2025, at 5:24 PM, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we’d take a swing at
adding isReadable/isWriteable methods to ReflectionProperty. Took a
while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

Hi folks.

The holiday blackout period is over, and there’s nothing else really to discuss on this PR, so consider this an Intent to Vote notice for the isReadable RFC.

I’ll call the vote later this week, baring any new serious constructive feedback.

–Larry Garfield

Hi,

The RFC says:

To use “my current scope,” the static::class construct is an easy way to specify “whatever class this code is running in.”

The code is running in self::class or __CLASS__, not in static::class.


As noted in the RFC, isReadable() will give unavoidable false-positives (returning true although attempt to read the property will error). But there is also a false-negative:


class C {

function __construct(
readonly private mixed $foo
) { }

function __get($x) {
if ($x === 'foo') {
return $this->foo;
}
throw new Error('Undefined property '.$x);
}

function __isset($x) {
if ($x === 'foo')
return isset($this->foo); // not `true`, otherwise `isset(new C(null)->foo)` will return an incorrect result.
}
return false;
}
}

$c = new C(null);

// will return false, although it is readable
var_dump(new ReflectionProperty($c, 'foo')->isReadable(null, $c));

One could skip the __isset() check in order to avoid the false-negative, at the cost of more false-positives. I don’t know what is best, because I tend to avoid __get() like the plague anyway.

—Claude

On Wed, Jan 14, 2026, at 2:00 PM, Claude Pache wrote:

Le 13 janv. 2026 à 22:30, Larry Garfield <larry@garfieldtech.com> a écrit :

On Wed, Nov 5, 2025, at 5:24 PM, Larry Garfield wrote:

In other news, Ilija and I said a year ago that we'd take a swing at
adding isReadable/isWriteable methods to ReflectionProperty. Took a
while, but here we are. A strangely small RFC from us:

PHP: rfc:isreadable-iswriteable

Hi folks.

The holiday blackout period is over, and there's nothing else really to discuss on this PR, so consider this an Intent to Vote notice for the isReadable RFC.

I'll call the vote later this week, baring any new serious constructive feedback.

--Larry Garfield

Hi,

The RFC says:

To use “my current scope,” the `static::class` construct is an easy way to specify “whatever class this code is running in.”

The code is running in `self::class` or `__CLASS__`, not in `static::class`.

Hm, good point. I've changed to to `self::class`, which I believe should only be an Editorial change. (There's no change to the design, just to the explanation, and it's arguably a typo.) I'll give it another day before opening the vote just in case.

As noted in the RFC, `isReadable()` will give unavoidable
false-positives (returning `true` although attempt to read the property
will error). But there is also a false-negative:

class C {

    function __construct(
        readonly private mixed $foo
    ) { }
  
    function __get($x) {
        if ($x === 'foo') {
            return $this->foo;
        }
        throw new Error('Undefined property '.$x);
    }

    function __isset($x) {
        if ($x === 'foo')
            return isset($this->foo); // not `true`, otherwise 
`isset(new C(null)->foo)` will return an incorrect result.
        }
        return false;
    }
}

$c = new C(null);

// will return false, although it is readable
var_dump(new ReflectionProperty($c, 'foo')->isReadable(null, $c));

One could skip the `__isset()` check in order to avoid the
false-negative, at the cost of more false-positives. I don’t know what
is best, because I tend to avoid `__get()` like the plague anyway.

As discussed earlier in the thread and noted in the RFC, as long as hooks and __get support arbitrary code, we can never guarantee no false positives or negatives. Based on the earlier discussion, the current setup seems like the best balance for the expected typical cases. So we'd rather stick with how it is now.

--Larry Garfield