Skip to content

Releases: Ocramius/ProxyManager

2.0.4

05 Nov 09:08
Compare
Choose a tag to compare

Build Status

Fixed

  • Remove deprecated getMock usage from tests #325
  • Fix incorrect type in docs example #329
  • _get method support in lazy loading value holders #344
  • Fix #344 - lazy loading value holder magic method support #345

2.0.3

01 Jul 12:14
2.0.3
Compare
Choose a tag to compare

2.0.2

27 May 02:07
2.0.2
Compare
Choose a tag to compare

Build Status

2.0.2

Fixed

  • Various optimizations were performed in the ocramius/package-versions
    integration in order to prevent "class not found" fatals. #294
  • Null objects produced via a given class name were not extending from the given class name, causing obvious LSP
    compliance and type-compatibility issues. #300
    #301
  • Specific installation versions were removed from the README.md install instructions, since composer
    is installing the latest available version by default. #305
  • PHP 7.0.6 support was dropped. PHP 7.0.6 includes some nasty reflection bugs that caused __isset to be called when
    ReflectionProperty#getValue() is used (https://bugs.php.net/72174).
    #306
    #308
  • PHP 7.0.7 contains additional limitations as to when $this can be used. Specifically, $this cannot be used as a
    parameter name for closures that have an already assigned $this. Due to $this being incorrectly used as parameter
    name within this library, running ProxyManager on PHP 7.0.7 would have caused a fatal error.
    #306
    #308
    #316
  • PHP 7.1.0-DEV includes type-checks for incompatible arithmetic operations: some of those operations were erroneously
    performed in the library internals. #308

Total issues resolved: 12

2.0.1

2.0.0

30 Jan 09:41
2.0.0
Compare
Choose a tag to compare

Build Status

New features

PHP 7 support

ProxyManager will now correctly operate in PHP 7 environments.

PHP 7 Return type hints

ProxyManager will now correctly mimic signatures of methods with return type hints:

class SayHello
{
    public function hello() : string
    {
        return 'hello!';
    }
}

PHP 7 Scalar type hints

ProxyManager will now correctly mimic signatures of methods with scalar type hints

class SayHello
{
    public function hello(string $name) : string
    {
        return 'hello, ' . $name;
    }
}

PHP 5.6 Variadics support

ProxyManager will now correctly mimic behavior of methods with variadic parameters:

class SayHello
{
    public function hello(string ...$names) : string
    {
        return 'hello, ' . implode(', ', $names);
    }
}

By-ref variadic arguments are also supported:

class SayHello
{
    public function hello(string ... & $names)
    {
        foreach ($names as & $name) {
            $name = 'hello, ' . $name;
        }
    }
}

Constructors in proxies are not replaced anymore

In ProxyManager v1.x, the constructor of a proxy was completely replaced with a method
accepting proxy-specific parameters.

This is no longer true, and you will be able to use the constructor of your objects as
if the class wasn't proxied at all:

class SayHello
{
    public function __construct()
    {
        echo 'Hello!';
    }
}

/* @var $proxyGenerator \ProxyManager\ProxyGenerator\ProxyGeneratorInterface */
$proxyClass = $proxyGenerator->generateProxy(
    new ReflectionClass(SayHello::class),
    new ClassGenerator('ProxyClassName')
);

eval('<?php ' . $proxyClass->generate());

$proxyName = $proxyClass->getName();
$object = new ProxyClassName(); // echoes "Hello!"

var_dump($object); // a proxy object

If you still want to manually build a proxy (without factories), a
public static staticProxyConstructor method is added to the generated proxy classes.

Friend classes support

You can now access state of "friend objects" at any time.

class EmailAddress
{
    private $address;

    public function __construct(string $address)
    {
        assertEmail($address);

        $this->address = $address;
    }

    public function equalsTo(EmailAddress $other)
    {
        return $this->address === $other->address;
    }
}

When using lazy-loading or access-interceptors, the equalsTo method will
properly work, as even protected and private access are now correctly proxied.

Ghost objects now only lazy-load on state-access

Lazy loading ghost objects now trigger lazy-loading only when their state is accessed.
This also implies that lazy loading ghost objects cannot be used with interfaces anymore.

class AccessPolicy
{
    private $policyName;

    /**
     * Calling this method WILL cause lazy-loading, when using a ghost object,
     * as the method is accessing the object's state
     */
    public function getPolicyName() : string
    {
        return $this->policyName;        
    }

    /**
     * Calling this method WILL NOT cause lazy-loading, when using a ghost object,
     * as the method is not reading any from the object.
     */
    public function allowAccess() : bool
    {
        return false;
    }
}

Faster ghost object state initialization

Lazy loading ghost objects can now be initialized in a more efficient way, by avoiding
reflection or setters:

class Foo
{
    private $a;
    protected $b;
    public $c;
}

$factory = new \ProxyManager\Factory\LazyLoadingGhostFactory();

$proxy = $factory-createProxy(
    Foo::class,
    function (
        GhostObjectInterface $proxy, 
        string $method, 
        array $parameters, 
        & $initializer,
        array $properties
    ) {
        $initializer   = null;

        $properties["\0Foo\0a"] = 'abc';
        $properties["\0*\0b"]   = 'def';
        $properties['c']        = 'ghi';

        return true;
    }
);


$reflectionA = new ReflectionProperty(Foo::class, 'a');
$reflectionA->setAccessible(true);

var_dump($reflectionA->getValue($proxy)); // dumps "abc"

$reflectionB = new ReflectionProperty(Foo::class, 'b');
$reflectionB->setAccessible(true);

var_dump($reflectionB->getValue($proxy)); // dumps "def"

var_dump($proxy->c); // dumps "ghi"

Skipping lazy-loaded properties in generated proxies

Lazy loading ghost objects can now skip lazy-loading for certain properties.
This is especially useful when you have properties that are always available,
such as identifiers of entities:

class User
{
    private $id;
    private $username;

    public function getId() : int
    {
        return $this->id;
    }

    public function getUsername() : string
    {
        return $this->username;
    }
}

/* @var $proxy User */
$proxy = (new \ProxyManager\Factory\LazyLoadingGhostFactory())->createProxy(
    User::class,
    function (
        GhostObjectInterface $proxy,
        string $method,
        array $parameters,
        & $initializer,
        array $properties
    ) {
        $initializer   = null;

        var_dump('Triggered lazy-loading!');

        $properties["\0User\0username"] = 'Ocramius';

        return true;
    },
    [
        'skippedProperties' => [
            "\0User\0id",
        ],
    ]
);

$idReflection = new \ReflectionProperty(User::class, 'id');

$idReflection->setAccessible(true);
$idReflection->setValue($proxy, 123);

var_dump($proxy->getId());       // 123
var_dump($proxy->getUsername()); // "Triggered lazy-loading!", then "Ocramius"

Proxies are now always generated on-the-fly by default

Proxies are now automatically generated any time you require them: no configuration
needed. If you want to gain better performance, you may still want to read
the tuning for production docs.

Proxy names are now hashed, simplified signature is attached to them

Proxy classes now have shorter names, as the parameters used to generate them are
hashed into their name. A signature is attached to proxy classes (as a private static
property) so that proxy classes aren't re-used across library updates.
Upgrading ProxyManager will now cause all proxies to be re-generated automatically,
while the old proxy files are going to be ignored.

BC Breaks - backwards-incompatible changes

  • PHP ~7.0 is now required to use ProxyManager
  • HHVM compatibility is not guaranteed, as HHVM is not yet PHP 7 compliant
  • All classes and interfaces now use strict scalar type hints.
    If you extended or implemented anything from the ProxyManager\ namespace, you probably need to change
    that code to adapt it to the new signature.
  • All classes and interfaces now use return type declarations.
    If you extended or implemented anything from the ProxyManager\ namespace, you probably need to change
    that code to adapt it to the new signature.
  • ProxyManager will no longer write proxies to disk by default:
    the EvaluatingGeneratorStrategy is used instead.
    If you still want ProxyManager to write files to disk, please refer to the tuning for production docs
  • Ghost objects were entirely rewritten, for better support and improved performance. Lazy-loading is not
    triggered by public API access, but by property access (private and public). While this is not really a BC
    break, you are encouraged to check your applications if you rely on ghost objects.
  • If ProxyManager can't find a proxy, it will now automatically attempt to auto-generate it, regardless of
    the settings passed to it.
  • ProxyManager\Configuration#setAutoGenerateProxies() was removed. Please look for calls to this method and
    remove them.
  • Private properties are now also correctly handled by ProxyManager: accessing proxy state via friend classes
    (protected or private scope) does not require any particular workarounds anymore.
  • ProxyManager\Version::VERSION was removed. Please use ProxyManager\Version::getVersion() instead.
  • PHP 4 style constructors are no longer supported

Changes (raw log)

Total issues resolved: 66

Read more

2.0.0-BETA3

29 Jan 10:22
2.0.0-BETA3
Compare
Choose a tag to compare
2.0.0-BETA3 Pre-release
Pre-release

Build Status

This is the third beta release of the 2.0.0 series.

Users are encouraged to try this new version, and to verify if there are any BC breaks other than the documented ones.

You can install this component by running:

composer require ocramius/proxy-manager:2.0.0-BETA3@BETA

New features

PHP 7 support

ProxyManager will now correctly operate in PHP 7 environments.

PHP 7 Return type hints

ProxyManager will now correctly mimic signatures of methods with return type hints:

class SayHello
{
    public function hello() : string
    {
        return 'hello!';
    }
}

PHP 7 Scalar type hints

ProxyManager will now correctly mimic signatures of methods with scalar type hints

class SayHello
{
    public function hello(string $name) : string
    {
        return 'hello, ' . $name;
    }
}

PHP 5.6 Variadics support

ProxyManager will now correctly mimic behavior of methods with variadic parameters:

class SayHello
{
    public function hello(string ...$names) : string
    {
        return 'hello, ' . implode(', ', $names);
    }
}

By-ref variadic arguments are also supported:

class SayHello
{
    public function hello(string ... & $names)
    {
        foreach ($names as & $name) {
            $name = 'hello, ' . $name;
        }
    }
}

Constructors in proxies are not replaced anymore

In ProxyManager v1.x, the constructor of a proxy was completely replaced with a method
accepting proxy-specific parameters.

This is no longer true, and you will be able to use the constructor of your objects as
if the class wasn't proxied at all:

class SayHello
{
    public function __construct()
    {
        echo 'Hello!';
    }
}

/* @var $proxyGenerator \ProxyManager\ProxyGenerator\ProxyGeneratorInterface */
$proxyClass = $proxyGenerator->generateProxy(
    new ReflectionClass(SayHello::class),
    new ClassGenerator('ProxyClassName')
);

eval('<?php ' . $proxyClass->generate());

$proxyName = $proxyClass->getName();
$object = new ProxyClassName(); // echoes "Hello!"

var_dump($object); // a proxy object

If you still want to manually build a proxy (without factories), a
public static staticProxyConstructor method is added to the generated proxy classes.

Friend classes support

You can now access state of "friend objects" at any time.

class EmailAddress
{
    private $address;

    public function __construct(string $address)
    {
        assertEmail($address);

        $this->address = $address;
    }

    public function equalsTo(EmailAddress $other)
    {
        return $this->address === $other->address;
    }
}

When using lazy-loading or access-interceptors, the equalsTo method will
properly work, as even protected and private access are now correctly proxied.

Ghost objects now only lazy-load on state-access

Lazy loading ghost objects now trigger lazy-loading only when their state is accessed.
This also implies that lazy loading ghost objects cannot be used with interfaces anymore.

class AccessPolicy
{
    private $policyName;

    /**
     * Calling this method WILL cause lazy-loading, when using a ghost object,
     * as the method is accessing the object's state
     */
    public function getPolicyName() : string
    {
        return $this->policyName;        
    }

    /**
     * Calling this method WILL NOT cause lazy-loading, when using a ghost object,
     * as the method is not reading any from the object.
     */
    public function allowAccess() : bool
    {
        return false;
    }
}

Faster ghost object state initialization

Lazy loading ghost objects can now be initialized in a more efficient way, by avoiding
reflection or setters:

class Foo
{
    private $a;
    protected $b;
    public $c;
}

$factory = new \ProxyManager\Factory\LazyLoadingGhostFactory();

$proxy = $factory-createProxy(
    Foo::class,
    function (
        GhostObjectInterface $proxy, 
        string $method, 
        array $parameters, 
        & $initializer,
        array $properties
    ) {
        $initializer   = null;

        $properties["\0Foo\0a"] = 'abc';
        $properties["\0*\0b"]   = 'def';
        $properties['c']        = 'ghi';

        return true;
    }
);


$reflectionA = new ReflectionProperty(Foo::class, 'a');
$reflectionA->setAccessible(true);

var_dump($reflectionA->getValue($proxy)); // dumps "abc"

$reflectionB = new ReflectionProperty(Foo::class, 'b');
$reflectionB->setAccessible(true);

var_dump($reflectionB->getValue($proxy)); // dumps "def"

var_dump($proxy->c); // dumps "ghi"

Skipping lazy-loaded properties in generated proxies

Lazy loading ghost objects can now skip lazy-loading for certain properties.
This is especially useful when you have properties that are always available,
such as identifiers of entities:

class User
{
    private $id;
    private $username;

    public function getId() : int
    {
        return $this->id;
    }

    public function getUsername() : string
    {
        return $this->username;
    }
}

/* @var $proxy User */
$proxy = (new \ProxyManager\Factory\LazyLoadingGhostFactory())->createProxy(
    User::class,
    function (
        GhostObjectInterface $proxy,
        string $method,
        array $parameters,
        & $initializer,
        array $properties
    ) {
        $initializer   = null;

        var_dump('Triggered lazy-loading!');

        $properties["\0User\0username"] = 'Ocramius';

        return true;
    },
    [
        'skippedProperties' => [
            "\0User\0id",
        ],
    ]
);

$idReflection = new \ReflectionProperty(User::class, 'id');

$idReflection->setAccessible(true);
$idReflection->setValue($proxy, 123);

var_dump($proxy->getId());       // 123
var_dump($proxy->getUsername()); // "Triggered lazy-loading!", then "Ocramius"

Proxies are now always generated on-the-fly by default

Proxies are now automatically generated any time you require them: no configuration
needed. If you want to gain better performance, you may still want to read
the tuning for production docs.

Proxy names are now hashed, simplified signature is attached to them

Proxy classes now have shorter names, as the parameters used to generate them are
hashed into their name. A signature is attached to proxy classes (as a private static
property) so that proxy classes aren't re-used across library updates.
Upgrading ProxyManager will now cause all proxies to be re-generated automatically,
while the old proxy files are going to be ignored.

BC Breaks - backwards-incompatible changes

  • PHP ~7.0 is now required to use ProxyManager
  • HHVM compatibility is not guaranteed, as HHVM is not yet PHP 7 compliant
  • All classes and interfaces now use strict scalar type hints.
    If you extended or implemented anything from the ProxyManager\ namespace, you probably need to change
    that code to adapt it to the new signature.
  • All classes and interfaces now use return type declarations.
    If you extended or implemented anything from the ProxyManager\ namespace, you probably need to change
    that code to adapt it to the new signature.
  • ProxyManager will no longer write proxies to disk by default:
    the EvaluatingGeneratorStrategy is used instead.
    If you still want ProxyManager to write files to disk, please refer to the tuning for production docs
  • Ghost objects were entirely rewritten, for better support and improved performance. Lazy-loading is not
    triggered by public API access, but by property access (private and public). While this is not really a BC
    break, you are encouraged to check your applications if you rely on ghost objects.
  • If ProxyManager can't find a proxy, it will now automatically attempt to auto-generate it, regardless of
    the settings passed to it.
  • ProxyManager\Configuration#setAutoGenerateProxies() was removed. Please look for calls to this method and
    remove them.
  • Private properties are now also correctly handled by ProxyManager: accessing proxy state via friend classes
    (protected or private scope) does not require any particular workarounds anymore.
  • ProxyManager\Version::VERSION was removed. Please use ProxyManager\Version::getVersion() instead.
  • PHP 4 style constructors are no longer supported

Changes (raw log)

Total issues resolved: 65

Read more

2.0.0-BETA2

26 Jan 18:32
2.0.0-BETA2
Compare
Choose a tag to compare
2.0.0-BETA2 Pre-release
Pre-release

Build Status

This is the second beta release of the 2.0.0 series.

Details on the new features will follow in further release notes.
For now, existing users are encouraged to try this new version, and to verify if there are any BC breaks other than the documented ones.

You can install this component by running:

composer require ocramius/proxy-manager:2.0.0@BETA

Total issues resolved: 59

2.0.0-BETA1

23 Jan 02:12
Compare
Choose a tag to compare
2.0.0-BETA1 Pre-release
Pre-release

Build Status

This is the first beta release of the 2.0.0 series.

Details on the new features will follow in further release notes.
For now, existing users are encouraged to try this new version, and to verify if there are any BC breaks other than the documented ones.

You can install this component by running:

composer require ocramius/proxy-manager:2.0.0@BETA

Total issues resolved: 59

1.0.2

10 Aug 13:02
1.0.2
Compare
Choose a tag to compare

1.0.1

09 Aug 23:27
1.0.1
Compare
Choose a tag to compare
1.0.1 Pre-release
Pre-release

Build Status

Total issues resolved: 2

Note: this release was incorrectly tagged, please use 1.0.2 instead.