diff --git a/components/var_exporter.rst b/components/var_exporter.rst index c7ec9cd90d0..031e285d0c5 100644 --- a/components/var_exporter.rst +++ b/components/var_exporter.rst @@ -207,169 +207,5 @@ pattern, which also works with abstract classes, internal classes, and interface Use this mechanism only when native lazy objects cannot be leveraged (otherwise you'll get a deprecation notice). -Legacy Creation of Lazy Objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When using a PHP version earlier than 8.4, native lazy objects are not available. -In these cases, the VarExporter component provides two traits that help you -implement lazy-loading mechanisms in your classes. - -.. _var-exporter_ghost-objects: - -LazyGhostTrait -.............. - -.. deprecated:: 7.3 - - ``LazyGhostTrait`` is deprecated since Symfony 7.3. Use PHP 8.4's native lazy - objects instead. Note that using the trait with PHP versions earlier than 8.4 - does not trigger a deprecation, to ease the transition. - -Ghost objects are empty objects, which see their properties populated the first -time any method is called. Thanks to :class:`Symfony\\Component\\VarExporter\\LazyGhostTrait`, -the implementation of the lazy mechanism is eased. The ``MyLazyObject::populateHash()`` -method will be called only when the object is actually used and needs to be -initialized:: - - namespace App\Hash; - - use Symfony\Component\VarExporter\LazyGhostTrait; - - class HashProcessor - { - use LazyGhostTrait; - - // This property may require a heavy computation to have its value - public readonly string $hash; - - public function __construct() - { - self::createLazyGhost(initializer: $this->populateHash(...), instance: $this); - } - - private function populateHash(array $data): void - { - // Compute $this->hash value with the passed data - } - } - -:class:`Symfony\\Component\\VarExporter\\LazyGhostTrait` also allows to -convert non-lazy classes to lazy ones:: - - namespace App\Hash; - - use Symfony\Component\VarExporter\LazyGhostTrait; - - class HashProcessor - { - public readonly string $hash; - - public function __construct(array $data) - { - $this->populateHash($data); - } - - private function populateHash(array $data): void - { - // ... - } - - public function validateHash(): bool - { - // ... - } - } - - class LazyHashProcessor extends HashProcessor - { - use LazyGhostTrait; - } - - $processor = LazyHashProcessor::createLazyGhost(initializer: function (HashProcessor $instance): void { - // Do any operation you need here: call setters, getters, methods to validate the hash, etc. - $data = /** Retrieve required data to compute the hash */; - $instance->__construct(...$data); - $instance->validateHash(); - }); - -While you never query ``$processor->hash`` value, heavy methods will never be -triggered. But still, the ``$processor`` object exists and can be used in your -code, passed to methods, functions, etc. - -Ghost objects unfortunately can't work with abstract classes or internal PHP -classes. Nevertheless, the VarExporter component covers this need with the help -of :ref:`Virtual Proxies `. - -.. _var-exporter_virtual-proxies: - -LazyProxyTrait -.............. - -.. deprecated:: 7.3 - - ``LazyProxyTrait`` is deprecated since Symfony 7.3. Use PHP 8.4's native lazy - objects instead. Note that using the trait with PHP versions earlier than 8.4 - does not trigger a deprecation, to ease the transition. - -The purpose of virtual proxies in the same one as -:ref:`ghost objects `, but their internal behavior is -totally different. Where ghost objects requires to extend a base class, virtual -proxies take advantage of the **Liskov Substitution principle**. This principle -describes that if two objects are implementing the same interface, you can swap -between the different implementations without breaking your application. This is -what virtual proxies take advantage of. To use virtual proxies, you may use -:class:`Symfony\\Component\\VarExporter\\ProxyHelper` to generate proxy's class -code:: - - namespace App\Hash; - - use Symfony\Component\VarExporter\ProxyHelper; - - interface ProcessorInterface - { - public function getHash(): bool; - } - - abstract class AbstractProcessor implements ProcessorInterface - { - protected string $hash; - - public function getHash(): bool - { - return $this->hash; - } - } - - class HashProcessor extends AbstractProcessor - { - public function __construct(array $data) - { - $this->populateHash($data); - } - - private function populateHash(array $data): void - { - // ... - } - } - - $proxyCode = ProxyHelper::generateLazyProxy(new \ReflectionClass(AbstractProcessor::class)); - // $proxyCode contains the actual proxy and the reference to LazyProxyTrait. - // In production env, this should be dumped into a file to avoid calling eval(). - eval('class HashProcessorProxy'.$proxyCode); - - $processor = HashProcessorProxy::createLazyProxy(initializer: function (): ProcessorInterface { - $data = /** Retrieve required data to compute the hash */; - $instance = new HashProcessor(...$data); - - // Do any operation you need here: call setters, getters, methods to validate the hash, etc. - - return $instance; - }); - -Just like ghost objects, while you never query ``$processor->hash``, its value -will not be computed. The main difference with ghost objects is that this time, -a proxy of an abstract class was created. This also works with internal PHP class. - .. _`OPcache`: https://www.php.net/opcache .. _`PSR-2`: https://www.php-fig.org/psr/psr-2/