Ocramius/ProxyManager

AccessInterceptorValueHolder which proxies a parent __get triggers E_USER_NOTICE

arjenm opened this issue · 0 comments

When you generate a AccessInterceptorValueHolder proxy, a E_USER_NOTICE is always triggered when a property is not defined on the class, even if the that class has a __get-method.

This is caused by the getPublicAccessSimulationCode call here:

$callParent = PublicScopeSimulator::getPublicAccessSimulationCode(

And results in something like:

Notice: Undefined property: TestGet::$thisShouldNotGiveANotice in test.php on line ...

In contrast, the LazyLoadingValueHolder's __get-proxy does check for the parent and skips the call to getPublicAccessSimulationCode

And lastly the AccessInterceptorScopeLocalizer also doesn't give a notice about a undefined property (although it does cause, "Notice: Only variables should be assigned by reference")

Here is some test code:

use ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory;
use ProxyManager\Factory\AccessInterceptorValueHolderFactory;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;

error_reporting(E_ALL);

class TestGet {
    public string $notViaGet = 'not via __get';

    public function __get(string $name): string
    {
        return $name;
    }
}

// Class directly
// These don't give a notice
echo (new TestGet())->notViaGet, PHP_EOL;
echo (new TestGet())->thisShouldNotGiveANotice, PHP_EOL;

// LazyLoadingValueHolder
$lazyProxy = (new LazyLoadingValueHolderFactory())->createProxy(TestGet::class,
    function (&$wrappedObject, $proxy, $method, $parameters, &$initializer) {
        $wrappedObject = new TestGet();
        $initializer   = null;

        return true;
    }
);

// Neither do these
echo $lazyProxy->notViaGet, PHP_EOL;
echo $lazyProxy->thisShouldNotGiveANotice, PHP_EOL;

// AccessInterceptorValueHolder
$interceptorValueProxy = (new AccessInterceptorValueHolderFactory())->createProxy(
    new TestGet(),
);

// No notice
echo $interceptorValueProxy->notViaGet, PHP_EOL;
// But this one does give a notice: "Notice: Undefined property: TestGet::$thisShouldNotGiveANotice"
echo $interceptorValueProxy->thisShouldNotGiveANotice, PHP_EOL;

// AccessInterceptorScopeLocalizer
$interceptorScopeProxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy(
    new TestGet(),
);

// This results in "Notice: Only variables should be assigned by reference"
echo '$interceptorScopeProxy->thisDoesNotGiveANotice', PHP_EOL;