diff options
Diffstat (limited to 'vendor/symfony/var-exporter/README.md')
-rw-r--r-- | vendor/symfony/var-exporter/README.md | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md new file mode 100644 index 0000000..7195270 --- /dev/null +++ b/vendor/symfony/var-exporter/README.md | |||
@@ -0,0 +1,137 @@ | |||
1 | VarExporter Component | ||
2 | ===================== | ||
3 | |||
4 | The VarExporter component provides various tools to deal with the internal state | ||
5 | of objects: | ||
6 | |||
7 | - `VarExporter::export()` allows exporting any serializable PHP data structure to | ||
8 | plain PHP code. While doing so, it preserves all the semantics associated with | ||
9 | the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, | ||
10 | `__serialize`, `__unserialize`); | ||
11 | - `Instantiator::instantiate()` creates an object and sets its properties without | ||
12 | calling its constructor nor any other methods; | ||
13 | - `Hydrator::hydrate()` can set the properties of an existing object; | ||
14 | - `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy. | ||
15 | |||
16 | VarExporter::export() | ||
17 | --------------------- | ||
18 | |||
19 | The reason to use `VarExporter::export()` *vs* `serialize()` or | ||
20 | [igbinary](https://github.com/igbinary/igbinary) is performance: thanks to | ||
21 | OPcache, the resulting code is significantly faster and more memory efficient | ||
22 | than using `unserialize()` or `igbinary_unserialize()`. | ||
23 | |||
24 | Unlike `var_export()`, this works on any serializable PHP value. | ||
25 | |||
26 | It also provides a few improvements over `var_export()`/`serialize()`: | ||
27 | |||
28 | * the output is PSR-2 compatible; | ||
29 | * the output can be re-indented without messing up with `\r` or `\n` in the data; | ||
30 | * missing classes throw a `ClassNotFoundException` instead of being unserialized | ||
31 | to `PHP_Incomplete_Class` objects; | ||
32 | * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` | ||
33 | instances are preserved; | ||
34 | * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes | ||
35 | throw an exception when being serialized (their unserialized version is broken | ||
36 | anyway, see https://bugs.php.net/76737). | ||
37 | |||
38 | Instantiator and Hydrator | ||
39 | ------------------------- | ||
40 | |||
41 | `Instantiator::instantiate($class)` creates an object of the given class without | ||
42 | calling its constructor nor any other methods. | ||
43 | |||
44 | `Hydrator::hydrate()` sets the properties of an existing object, including | ||
45 | private and protected ones. For example: | ||
46 | |||
47 | ```php | ||
48 | // Sets the public or protected $object->propertyName property | ||
49 | Hydrator::hydrate($object, ['propertyName' => $propertyValue]); | ||
50 | |||
51 | // Sets a private property defined on its parent Bar class: | ||
52 | Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); | ||
53 | |||
54 | // Alternative way to set the private $object->privateBarProperty property | ||
55 | Hydrator::hydrate($object, [], [ | ||
56 | Bar::class => ['privateBarProperty' => $propertyValue], | ||
57 | ]); | ||
58 | ``` | ||
59 | |||
60 | `Lazy*Trait` | ||
61 | ------------ | ||
62 | |||
63 | The component provides two lazy-loading patterns: ghost objects and virtual | ||
64 | proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference). | ||
65 | |||
66 | Ghost objects work only with concrete and non-internal classes. In the generic | ||
67 | case, they are not compatible with using factories in their initializer. | ||
68 | |||
69 | Virtual proxies work with concrete, abstract or internal classes. They provide an | ||
70 | API that looks like the actual objects and forward calls to them. They can cause | ||
71 | identity problems because proxies might not be seen as equivalents to the actual | ||
72 | objects they proxy. | ||
73 | |||
74 | Because of this identity problem, ghost objects should be preferred when | ||
75 | possible. Exceptions thrown by the `ProxyHelper` class can help decide when it | ||
76 | can be used or not. | ||
77 | |||
78 | Ghost objects and virtual proxies both provide implementations for the | ||
79 | `LazyObjectInterface` which allows resetting them to their initial state or to | ||
80 | forcibly initialize them when needed. Note that resetting a ghost object skips | ||
81 | its read-only properties. You should use a virtual proxy to reset read-only | ||
82 | properties. | ||
83 | |||
84 | ### `LazyGhostTrait` | ||
85 | |||
86 | By using `LazyGhostTrait` either directly in your classes or by using | ||
87 | `ProxyHelper::generateLazyGhost()`, you can make their instances lazy-loadable. | ||
88 | This works by creating these instances empty and by computing their state only | ||
89 | when accessing a property. | ||
90 | |||
91 | ```php | ||
92 | class FooLazyGhost extends Foo | ||
93 | { | ||
94 | use LazyGhostTrait; | ||
95 | } | ||
96 | |||
97 | $foo = FooLazyGhost::createLazyGhost(initializer: function (Foo $instance): void { | ||
98 | // [...] Use whatever heavy logic you need here | ||
99 | // to compute the $dependencies of the $instance | ||
100 | $instance->__construct(...$dependencies); | ||
101 | // [...] Call setters, etc. if needed | ||
102 | }); | ||
103 | |||
104 | // $foo is now a lazy-loading ghost object. The initializer will | ||
105 | // be called only when and if a *property* is accessed. | ||
106 | ``` | ||
107 | |||
108 | ### `LazyProxyTrait` | ||
109 | |||
110 | Alternatively, `LazyProxyTrait` can be used to create virtual proxies: | ||
111 | |||
112 | ```php | ||
113 | $proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(Foo::class)); | ||
114 | // $proxyCode contains the reference to LazyProxyTrait | ||
115 | // and should be dumped into a file in production envs | ||
116 | eval('class FooLazyProxy'.$proxyCode); | ||
117 | |||
118 | $foo = FooLazyProxy::createLazyProxy(initializer: function (): Foo { | ||
119 | // [...] Use whatever heavy logic you need here | ||
120 | // to compute the $dependencies of the $instance | ||
121 | $instance = new Foo(...$dependencies); | ||
122 | // [...] Call setters, etc. if needed | ||
123 | |||
124 | return $instance; | ||
125 | }); | ||
126 | // $foo is now a lazy-loading virtual proxy object. The initializer will | ||
127 | // be called only when and if a *method* is called. | ||
128 | ``` | ||
129 | |||
130 | Resources | ||
131 | --------- | ||
132 | |||
133 | * [Documentation](https://symfony.com/doc/current/components/var_exporter.html) | ||
134 | * [Contributing](https://symfony.com/doc/current/contributing/index.html) | ||
135 | * [Report issues](https://github.com/symfony/symfony/issues) and | ||
136 | [send Pull Requests](https://github.com/symfony/symfony/pulls) | ||
137 | in the [main Symfony repository](https://github.com/symfony/symfony) | ||