2.0.0
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 theProxyManager\
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 theProxyManager\
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:
theEvaluatingGeneratorStrategy
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 useProxyManager\Version::getVersion()
instead.- PHP 4 style constructors are no longer supported
Changes (raw log)
Total issues resolved: 66
- 97: Private properties of superclasses are not considered when generating proxies
- 105: Make the evaluating generator strategy a default
- 115: RFC: Recited: Give me my constructor back
- 128: Removal of PHP 5.3 support
- 130: [WIP\ Master branch dev version / 2.0.x dependencies
- 152: Rewrite Ghost Objects to only rely on property lazy loading
- 159: Ideas/considerations for GhostObject Proxies lazy loading
- 167: Drop PHP 5.4 support
- 175: Avoid constructor override
- 177: Add variadics support
- 184: Split documentation homepage into a "features" page, remove duplicate content
- 186: Remove deprecated
ProxyManager\Configuration#setAutoGenerateProxies()
- 192: Lazy-loading of ghost objects only via properties access (no method overrides)
- 200: Remove deprecated methods on ProxyManager\Configuration
- 203: Remove duplicated content on documentation #184
- 204: Cleanup: #167 - remove PHP 5.4 support
- 205: Skipping files/directories that are not needed in deployed versions of ProxyManager in the packaged version of the repo
- 208: Document new
GhostObject
behavior (property lazy-loading, by-ref initialization) - 209: Modify the strategy on Configuration#getGeneratorStrategy to use EvaluationGeneratorStrategy class as default
- 211: Move documentation to be generated by couscous
- 212: Allow skipping properties in
LazyLoadingGhost
for partial initialization - 214: Cleanup: unused classes removal (constructors, not needed as per #115 and #175)
- 215: Cleanup: unused imports
- 218: #97: handle private properties of superclasses
- 219: Cleanup: run codegen smoke-tests in same process
- 220: CS: imported symbols cleanups
- 221: Skip properties when use ghost objects
- 222: Hotfix: Ghost object generators cannot proxy interfaces, therefore should throw exceptions
- 224: Disable private/protected property checks during lazy loading initialization of GhostObjects
- 225: #224 - GhostObjects can simply ignore scope checks during lazy-loading (temporarily fixes #210)
- 232: Variadic function support
- 234: Fix html titles
- 237: remove unused title table at README.md ?
- 238: Fix title when rendering
- 239: Skip test inapplicable to php7
- 240: Support scalar type hints (PHP 7)
- 246: Don't suggest package that is already required.
- 247: Hotfix: PHP 7 warnings on binding internal classes
- 251: Hotfix - #249 file writer generator strategy rename failures (2.0.x rebase)
- 252: Moving to new travis build infrastructure
- 255: Fix: Use all the columns
- 256: Revert #254, add integration test for options in factory logic
- 261: Fix a typo in main.css stylesheet
- 263: Broken links in footer http://ocramius.github.io/ProxyManager/
- 264: Duplicate semicolons generated
- 265: Document limitation of pre-5.6 variadic usage
- 266: #265 - by-ref variadic support
- 267: #264 - duplicate semicolon removal
- 268: #263 - correcting links in the footer of the docs
- 271: Feature - #241 - support scalar type hints
- 272: Document 2.0.0 changes
- 273: The homepage of the doc is confusing
- 274: Add scalar and return type hints where applicable, use strict types
- 276: Test protected member access lazy loading (ghost objects)
- 277: Fix/#276 protected member access via friend objects
- 278: #274 - scalar type hints, return type hints, strict types
- 279: Feature - #274 void and missing return types
- 280: #273 - fix homepage docs link, fix presentation link
- 281: Docs - #208 document new ghost object behavior
- 282: Grammar improvements to lazy loading ghost object docs
- 283: Docs - #272 - document 2.0.0 changes
- 284: Remove the need for a
Version
class - 285: Feature - #284 - dynamic package version resolution
- 287: Docs - #272 - document 2.0.0 changes
- 288: #276 - testing friend object access against skipped properties
- 289: Suggested stability timeline for 2.x