Skip to content

Comparison

Olivier Laviale edited this page Oct 14, 2018 · 1 revision

Disclaimer: olvlvl's proxy generator is only that effective because it's designed to generate proxies for Symfony's dependency injection component, and cannot proxy services that don't have any interface, while symfony/proxy-manager-bridge uses ocramius/proxy-manager, which is a complete solution to create proxies, and not only DIC ones.

Please consider the following interface, its implementation, and some builder code:

<?php

namespace cases;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

interface SampleInterface
{
    public function getValue(): string;
}

class Sample implements SampleInterface
{
    /**
     * @var string
     */
    private $value;

    public function __construct(string $value)
    {
        $this->value = $value;
    }

    /**
     * @inheritdoc
     */
    public function getValue(): string
    {
        return $this->value;
    }
}

$builder = new ContainerBuilder();
$builder->addDefinitions([

    SampleInterface::class => (new Definition)
        ->setClass(Sample::class)
        ->setLazy(true)
        ->setPublic(true)
        ->addArgument('aValue')

]);
$builder->compile();

This is what the dumped container looks like with olvlvl's proxy generator:

<?php

// …

    protected function getSampleInterfaceService($lazyLoad = true)
    {
        if ($lazyLoad) {
            return $this->services['cases\SampleInterface'] = new class(
                function () {
                    return $this->getSampleInterfaceService(false);
                }
            ) implements \cases\SampleInterface
            {
                private $factory, $service;

                public function __construct(callable $factory)
                {
                    $this->factory = $factory;
                }

                public function getValue(): string
                {
                    return ($this->service ?: $this->service = ($this->factory)())->getValue();
                }
            };
        }

        return new \cases\Sample('aValue');
    }
}

And this is what it looks like with Symfony's:

<?php

// …
    protected function getSampleInterfaceService($lazyLoad = true)
    {
        if ($lazyLoad) {
            return $this->services['cases\SampleInterface'] = $this->createProxy('Sample_5107301', function () {
                return \Sample_5107301::staticProxyConstructor(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
                    $wrappedInstance = $this->getSampleInterfaceService(false);

                    $proxy->setProxyInitializer(null);

                    return true;
                });
            });
        }

        return new \cases\Sample('aValue');
    }
}

class Sample_5107301 extends \cases\Sample implements \ProxyManager\Proxy\VirtualProxyInterface
{

    /**
     * @var \Closure|null initializer responsible for generating the wrapped object
     */
    private $valueHolder85aa8 = null;

    /**
     * @var \Closure|null initializer responsible for generating the wrapped object
     */
    private $initializere3f84 = null;

    /**
     * @var bool[] map of public properties of the parent class
     */
    private static $publicPropertiese979b = [
        
    ];

    public function getValue() : string
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, 'getValue', array(), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        return $this->valueHolder85aa8->getValue();
    }

    /**
     * Constructor for lazy initialization
     *
     * @param \Closure|null $initializer
     */
    public static function staticProxyConstructor($initializer)
    {
        static $reflection;

        $reflection = $reflection ?? $reflection = new \ReflectionClass(__CLASS__);
        $instance = $reflection->newInstanceWithoutConstructor();

        \Closure::bind(function (\cases\Sample $instance) {
            unset($instance->value);
        }, $instance, 'cases\\Sample')->__invoke($instance);

        $instance->initializere3f84 = $initializer;

        return $instance;
    }

    public function __construct(string $value)
    {
        static $reflection;

        if (! $this->valueHolder85aa8) {
            $reflection = $reflection ?: new \ReflectionClass('cases\\Sample');
            $this->valueHolder85aa8 = $reflection->newInstanceWithoutConstructor();
        \Closure::bind(function (\cases\Sample $instance) {
            unset($instance->value);
        }, $this, 'cases\\Sample')->__invoke($this);

        }

        $this->valueHolder85aa8->__construct($value);
    }

    public function & __get($name)
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, '__get', ['name' => $name], $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        if (isset(self::$publicPropertiese979b[$name])) {
            return $this->valueHolder85aa8->$name;
        }

        $realInstanceReflection = new \ReflectionClass(get_parent_class($this));

        if (! $realInstanceReflection->hasProperty($name)) {
            $targetObject = $this->valueHolder85aa8;

            $backtrace = debug_backtrace(false);
            trigger_error(
                sprintf(
                    'Undefined property: %s::$%s in %s on line %s',
                    get_parent_class($this),
                    $name,
                    $backtrace[0]['file'],
                    $backtrace[0]['line']
                ),
                \E_USER_NOTICE
            );
            return $targetObject->$name;
            return;
        }

        $targetObject = $this->valueHolder85aa8;
        $accessor = function & () use ($targetObject, $name) {
            return $targetObject->$name;
        };
        $backtrace = debug_backtrace(true);
        $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub();
        $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject));
        $returnValue = & $accessor();

        return $returnValue;
    }

    public function __set($name, $value)
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, '__set', array('name' => $name, 'value' => $value), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        $realInstanceReflection = new \ReflectionClass(get_parent_class($this));

        if (! $realInstanceReflection->hasProperty($name)) {
            $targetObject = $this->valueHolder85aa8;

            return $targetObject->$name = $value;
            return;
        }

        $targetObject = $this->valueHolder85aa8;
        $accessor = function & () use ($targetObject, $name, $value) {
            return $targetObject->$name = $value;
        };
        $backtrace = debug_backtrace(true);
        $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub();
        $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject));
        $returnValue = & $accessor();

        return $returnValue;
    }

    public function __isset($name)
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, '__isset', array('name' => $name), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        $realInstanceReflection = new \ReflectionClass(get_parent_class($this));

        if (! $realInstanceReflection->hasProperty($name)) {
            $targetObject = $this->valueHolder85aa8;

            return isset($targetObject->$name);
            return;
        }

        $targetObject = $this->valueHolder85aa8;
        $accessor = function () use ($targetObject, $name) {
            return isset($targetObject->$name);
        };
        $backtrace = debug_backtrace(true);
        $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub();
        $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject));
        $returnValue = $accessor();

        return $returnValue;
    }

    public function __unset($name)
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, '__unset', array('name' => $name), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        $realInstanceReflection = new \ReflectionClass(get_parent_class($this));

        if (! $realInstanceReflection->hasProperty($name)) {
            $targetObject = $this->valueHolder85aa8;

            unset($targetObject->$name);
            return;
        }

        $targetObject = $this->valueHolder85aa8;
        $accessor = function () use ($targetObject, $name) {
            unset($targetObject->$name);
        };
        $backtrace = debug_backtrace(true);
        $scopeObject = isset($backtrace[1]['object']) ? $backtrace[1]['object'] : new \ProxyManager\Stub\EmptyClassStub();
        $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject));
        $returnValue = $accessor();

        return $returnValue;
    }

    public function __clone()
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, '__clone', array(), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        $this->valueHolder85aa8 = clone $this->valueHolder85aa8;
    }

    public function __sleep()
    {
        $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, '__sleep', array(), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;

        return array('valueHolder85aa8');
    }

    public function __wakeup()
    {
        \Closure::bind(function (\cases\Sample $instance) {
            unset($instance->value);
        }, $this, 'cases\\Sample')->__invoke($this);
    }

    public function setProxyInitializer(\Closure $initializer = null)
    {
        $this->initializere3f84 = $initializer;
    }

    public function getProxyInitializer()
    {
        return $this->initializere3f84;
    }

    public function initializeProxy() : bool
    {
        return $this->initializere3f84 && ($this->initializere3f84->__invoke($valueHolder85aa8, $this, 'initializeProxy', array(), $this->initializere3f84) || 1) && $this->valueHolder85aa8 = $valueHolder85aa8;
    }

    public function isProxyInitialized() : bool
    {
        return null !== $this->valueHolder85aa8;
    }

    public function getWrappedValueHolderValue() : ?object
    {
        return $this->valueHolder85aa8;
    }


}
Clone this wiki locally