Req #71254 [Opn]: Allow limited recursion with __get().

From: Date: Thu, 31 Dec 2015 02:11:12 +0000
Subject: Req #71254 [Opn]: Allow limited recursion with __get().
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-198329@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=71254&edit=1

 ID:                 71254
 User updated by:    andreas at dqxtech dot net
 Reported by:        andreas at dqxtech dot net
 Summary:            Allow limited recursion with __get().
 Status:             Open
 Type:               Feature/Change Request
 Package:            Class/Object related
 PHP Version:        7.0.2RC1
 Block user comment: N
 Private report:     N

 New Comment:

Hmm.. maybe the correct solution is not a stub, but a proxy (lazy instantiation).
And with that, every key in __get() is only called once.

A single proxy in the loop is sufficient to prevent the recursion and all problems caused by it.

A single stub in the loop is sufficient to prevent infinite recursion. But to also avoid duplicate
values in the buffer, one needs one stub per calc_*() method..

There is a trick to only need one stub in the circle:
https://3v4l.org/nXTYJ
But I'm not sure if I really like this, or if proxy is generally better.


Previous Comments:
------------------------------------------------------------------------
[2015-12-31 01:54:26] andreas at dqxtech dot net

Description:
------------
Currently, magic __get() refuses to dive into recursion if the same key is repeated.
https://3v4l.org/00Kuv

It stops, and gives a "Notice: Undefined property: C::$x".

There are cases where the recursion is not a bug, and it is indeed legitimate to dive one level into
the recursion.

As we can see, calling ->__get('x') explicitly instead of magic ->x, avoids the
notice. But this is undesirable, because we want the IDE to recognize that we are calling @property
$x.

The unlimited recursion can be avoided with stubs:
https://3v4l.org/Nb3VF

Proposal:
I want to propose that the recursion detection mechanic only gets active if the same key is used a
3rd time, not the 2nd time. This permits the legitimate case, but still prevents unlimited
recursion.

Test script:
---------------
<?php
class C {
    private $buffer = array();
    function __get($key) {
        if (array_key_exists($key, $this->buffer)) {
            return $this->buffer[$key];
        }
        $f = 'calc_' . $key;
        return $this->buffer[$key] = $this->$f();
    }
    function calc_x() {
        $x = new stdClass;
        // Set a stub to avoid infinite recursion.
        $this->buffer['x'] = $x;
        $x->y = $this->y;
        return $x;
    }
    function calc_y() {
        $y = new stdClass;
        // Set a stub to avoid infinite recursion.
        $this->buffer['y'] = $y;
        $y->x = $this->x;
        return $y;
    }
}



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=71254&edit=1


Thread (5 messages)

« previous php.bugs (#198329) next »