@@ -207,169 +207,5 @@ pattern, which also works with abstract classes, internal classes, and interface
207207Use this mechanism only when native lazy objects cannot be leveraged
208208(otherwise you'll get a deprecation notice).
209209
210- Legacy Creation of Lazy Objects
211- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212-
213- When using a PHP version earlier than 8.4, native lazy objects are not available.
214- In these cases, the VarExporter component provides two traits that help you
215- implement lazy-loading mechanisms in your classes.
216-
217- .. _var-exporter_ghost-objects :
218-
219- LazyGhostTrait
220- ..............
221-
222- .. deprecated :: 7.3
223-
224- ``LazyGhostTrait `` is deprecated since Symfony 7.3. Use PHP 8.4's native lazy
225- objects instead. Note that using the trait with PHP versions earlier than 8.4
226- does not trigger a deprecation, to ease the transition.
227-
228- Ghost objects are empty objects, which see their properties populated the first
229- time any method is called. Thanks to :class: `Symfony\\ Component\\ VarExporter\\ LazyGhostTrait `,
230- the implementation of the lazy mechanism is eased. The ``MyLazyObject::populateHash() ``
231- method will be called only when the object is actually used and needs to be
232- initialized::
233-
234- namespace App\Hash;
235-
236- use Symfony\Component\VarExporter\LazyGhostTrait;
237-
238- class HashProcessor
239- {
240- use LazyGhostTrait;
241-
242- // This property may require a heavy computation to have its value
243- public readonly string $hash;
244-
245- public function __construct()
246- {
247- self::createLazyGhost(initializer: $this->populateHash(...), instance: $this);
248- }
249-
250- private function populateHash(array $data): void
251- {
252- // Compute $this->hash value with the passed data
253- }
254- }
255-
256- :class: `Symfony\\ Component\\ VarExporter\\ LazyGhostTrait ` also allows to
257- convert non-lazy classes to lazy ones::
258-
259- namespace App\Hash;
260-
261- use Symfony\Component\VarExporter\LazyGhostTrait;
262-
263- class HashProcessor
264- {
265- public readonly string $hash;
266-
267- public function __construct(array $data)
268- {
269- $this->populateHash($data);
270- }
271-
272- private function populateHash(array $data): void
273- {
274- // ...
275- }
276-
277- public function validateHash(): bool
278- {
279- // ...
280- }
281- }
282-
283- class LazyHashProcessor extends HashProcessor
284- {
285- use LazyGhostTrait;
286- }
287-
288- $processor = LazyHashProcessor::createLazyGhost(initializer: function (HashProcessor $instance): void {
289- // Do any operation you need here: call setters, getters, methods to validate the hash, etc.
290- $data = /** Retrieve required data to compute the hash */;
291- $instance->__construct(...$data);
292- $instance->validateHash();
293- });
294-
295- While you never query ``$processor->hash `` value, heavy methods will never be
296- triggered. But still, the ``$processor `` object exists and can be used in your
297- code, passed to methods, functions, etc.
298-
299- Ghost objects unfortunately can't work with abstract classes or internal PHP
300- classes. Nevertheless, the VarExporter component covers this need with the help
301- of :ref: `Virtual Proxies <var-exporter_virtual-proxies >`.
302-
303- .. _var-exporter_virtual-proxies :
304-
305- LazyProxyTrait
306- ..............
307-
308- .. deprecated :: 7.3
309-
310- ``LazyProxyTrait `` is deprecated since Symfony 7.3. Use PHP 8.4's native lazy
311- objects instead. Note that using the trait with PHP versions earlier than 8.4
312- does not trigger a deprecation, to ease the transition.
313-
314- The purpose of virtual proxies in the same one as
315- :ref: `ghost objects <var-exporter_ghost-objects >`, but their internal behavior is
316- totally different. Where ghost objects requires to extend a base class, virtual
317- proxies take advantage of the **Liskov Substitution principle **. This principle
318- describes that if two objects are implementing the same interface, you can swap
319- between the different implementations without breaking your application. This is
320- what virtual proxies take advantage of. To use virtual proxies, you may use
321- :class: `Symfony\\ Component\\ VarExporter\\ ProxyHelper ` to generate proxy's class
322- code::
323-
324- namespace App\Hash;
325-
326- use Symfony\Component\VarExporter\ProxyHelper;
327-
328- interface ProcessorInterface
329- {
330- public function getHash(): bool;
331- }
332-
333- abstract class AbstractProcessor implements ProcessorInterface
334- {
335- protected string $hash;
336-
337- public function getHash(): bool
338- {
339- return $this->hash;
340- }
341- }
342-
343- class HashProcessor extends AbstractProcessor
344- {
345- public function __construct(array $data)
346- {
347- $this->populateHash($data);
348- }
349-
350- private function populateHash(array $data): void
351- {
352- // ...
353- }
354- }
355-
356- $proxyCode = ProxyHelper::generateLazyProxy(new \ReflectionClass(AbstractProcessor::class));
357- // $proxyCode contains the actual proxy and the reference to LazyProxyTrait.
358- // In production env, this should be dumped into a file to avoid calling eval().
359- eval('class HashProcessorProxy'.$proxyCode);
360-
361- $processor = HashProcessorProxy::createLazyProxy(initializer: function (): ProcessorInterface {
362- $data = /** Retrieve required data to compute the hash */;
363- $instance = new HashProcessor(...$data);
364-
365- // Do any operation you need here: call setters, getters, methods to validate the hash, etc.
366-
367- return $instance;
368- });
369-
370- Just like ghost objects, while you never query ``$processor->hash ``, its value
371- will not be computed. The main difference with ghost objects is that this time,
372- a proxy of an abstract class was created. This also works with internal PHP class.
373-
374210.. _`OPcache` : https://www.php.net/opcache
375211.. _`PSR-2` : https://www.php-fig.org/psr/psr-2/
0 commit comments