Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
virtual-proxy.html
001 <!DOCTYPE html>
002 <html class="no-js" id="top">
003 <head>
004 <title>ProxyManager - Virtual Proxy</title>
005
006 <meta name="description" content="A proxyManager write in php" />
007 <meta name="keywords" content="ProxyManager, proxy, manager, ocramius, Marco Pivetta, php, virtual proxy" />
008 <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
009 <link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600' rel='stylesheet' type='text/css'>
010 <link href="css/styles.css" rel="stylesheet" />
011 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/default.min.css">
012 <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/highlight.min.js"></script>
013 <script>hljs.initHighlightingOnLoad();</script>
014 <link rel="shortcut icon" href="favicon.ico">
015 </head>
016 <body>
017
018 <header class="site-header">
019 <div class="container">
020 <h1><a href="index.html"><img alt="ProxyManager" src="img/block.png" /></a></h1>
021
022 <nav class="main-nav" role="navigation">
023 <ul>
024 <li><a href="https://github.com/Ocramius/ProxyManager" target="_blank">Github</a>
025 <div class="bcms-clearfix"></div>
026 </li>
027 </ul>
028 </nav>
029 </div>
030 </header>
031 <main role="main">
032 <section class="component-content">
033
034 <div class="component-demo" id="live-demo">
035 <div class="container">
036 <div class="main-wrapper" style="text-align: right">
037 <iframe src="http://ghbtns.com/github-btn.html?user=ocramius&repo=ProxyManager&type=fork&count=true&size=large"
038 allowtransparency="true" frameborder="0" scrolling="0" width="310" height="40"></iframe>
039
040 <iframe src="http://ghbtns.com/github-btn.html?user=ocramius&repo=ProxyManager&type=watch&count=true&size=large"
041 allowtransparency="true" frameborder="0" scrolling="0" width="200" height="40"></iframe>
042
043 </div>
044 <div class="bcms-clearfix bcms-clearfix"></div>
045 </div>
046 </div>
047 <div class="component-info">
048 <div class="container">
049 <aside class="sidebar">
050 <nav class="spy-nav">
051 <ul>
052 <li><a href="index.html">Intro</a></li>
053 <li><a href="virtual-proxy.html">Virtual Proxy</a></li>
054 <li><a href="null-object.html">Null Objects</a></li>
055 <li><a href="ghost-object.html">Ghost Objects</a></li>
056 <li><a href="remote-object.html">Remote Object</a></li>
057 <li><a href="contributing.html">Contributing</a></li>
058 <li><a href="credits.html">Credits</a></li>
059 <li><a href="copyright.html">Copyright</a></li>
060 </ul>
061 </nav>
062 <div class="bcms-clearfix bcms-clearfix"></div>
063 <a class="btn btn-action btn-full download-component"
064 href="download.html">Download</a>
065 <div class="bcms-clearfix"></div>
066 </aside>
067
068 <div class="content">
069 <div class="bcms-clearfix"></div>
070 <h3 class="section-title">Lazy Loading Value Holder Proxy</h3>
071 <p>A lazy loading value holder proxy is a virtual proxy that wraps and lazily initializes a "real" instance of the proxied class.</p>
072 <hr />
073
074 <h3 class="section-title">What is lazy loading?</h3>
075
076 <p>In pseudo-code, in userland, <a href="http://www.martinfowler.com/eaaCatalog/lazyLoad.html" target="_blank">lazy loading</a> looks like following:</p>
077
078 <pre>
079 <code class="php">
080 class MyObjectProxy
081 {
082 private $wrapped;
083
084 public function doFoo()
085 {
086 $this->init();
087
088 return $this->wrapped->doFoo();
089 }
090
091 private function init()
092 {
093 if (null === $this->wrapped) {
094 $this->wrapped = new MyObject();
095 }
096 }
097 }
098 </code>
099 </pre>
100
101 <p>This code is problematic, and adds a lot of complexity that makes your unit tests' code even worse.</p>
102
103 <p>Also, this kind of usage often ends up in coupling your code with a particular <a href="http://martinfowler.com/articles/injection.html" target="_blank">Dependency Injection Container</a> or a framework that fetches dependencies for you. That way, further complexity is introduced, and some problems related with service location raise, as I've explained <a href="http://ocramius.github.io/blog/zf2-and-symfony-service-proxies-with-doctrine-proxies/" target="_blank">in this article</a>.</p>
104
105 <p>Lazy loading value holders abstract this logic for you, hiding your complex, slow, performance-impacting objects behind tiny wrappers that have their same API, and that get initialized at first usage.</p>
106
107 <hr />
108
109 <h3 class="section-title">When do I use a lazy value holder?</h3>
110
111 <p>You usually need a lazy value holder in cases where following applies</p>
112
113 <ul>
114 <li>your object takes a lot of time and memory to be initialized (with all dependencies)</li>
115 <li>your object is not always used, and the instantiation overhead can be avoided</li>
116 </ul>
117
118 <hr />
119
120 <h3 class="section-title">Usage examples</h3>
121
122 <p>ProxyManager provides a factory that eases instantiation of lazy loading value holders. To use it, follow these steps:</p>
123
124 <p>First of all, define your object's logic without taking care of lazy loading:</p>
125
126 <pre>
127 <code class="php">
128 namespace MyApp;
129
130 class HeavyComplexObject
131 {
132 public function __construct()
133 {
134 // just write your business logic
135 // don't worry about how heavy initialization of this will be!
136 }
137
138 public function doFoo() {
139 echo "OK!"
140 }
141 }
142 </code>
143 </pre>
144
145 <p>Then use the proxy manager to create a lazy version of the object (as a proxy):</p>
146
147 <pre>
148 <code class="php">
149 namespace MyApp;
150
151 use ProxyManager\Factory\LazyLoadingValueHolderFactory;
152 use ProxyManager\Proxy\LazyLoadingInterface;
153
154 require_once __DIR__ . '/vendor/autoload.php';
155
156 $factory = new LazyLoadingValueHolderFactory();
157 $initializer = function (& $wrappedObject, LazyLoadingInterface $proxy, $method, array $parameters, & $initializer) {
158 $initializer = null; // disable initialization
159 $wrappedObject = new HeavyComplexObject(); // fill your object with values here
160
161 return true; // confirm that initialization occurred correctly
162 };
163
164 $instance = $factory->createProxy('MyApp\HeavyComplexObject', $initializer);
165 </code>
166 </pre>
167
168 <p>You can now simply use your object as before:</p>
169
170 <pre>
171 <code class="php">
172 // this will just work as before
173 $proxy->doFoo(); // OK!
174 </code>
175 </pre>
176 <hr />
177
178
179 <h3 class="section-title">Lazy Initialization</h3>
180
181 <p>As you can see, we use a closure to handle lazy initialization of the proxy instance at runtime. The initializer closure signature should be as following:</p>
182
183 <pre>
184 <code class="php">
185 /**
186 * @var object $wrappedObject the instance (passed by reference) of the wrapped object,
187 * set it to your real object
188 * @var object $proxy the instance proxy that is being initialized
189 * @var string $method the name of the method that triggered lazy initialization
190 * @var string $parameters an ordered list of parameters passed to the method that
191 * triggered initialization, indexed by parameter name
192 * @var Closure $initializer a reference to the property that is the initializer for the
193 * proxy. Set it to null to disable further initialization
194 *
195 * @return bool true on success
196 */
197 $initializer = function (& $wrappedObject, $proxy, $method, $parameters, & $initializer) {};
198 </code>
199 </pre>
200
201 <p>The initializer closure should usually be coded like following:</p>
202
203 <pre>
204 <code class="php">
205 $initializer = function (& $wrappedObject, $proxy, $method, $parameters, & $initializer) {
206 $newlyCreatedObject = new Foo(); // instantiation logic
207 $newlyCreatedObject->setBar('baz') // instantiation logic
208 $newlyCreatedObject->setBat('bam') // instantiation logic
209
210 $wrappedObject = $newlyCreatedObject; // set wrapped object in the proxy
211 $initializer = null; // disable initializer
212
213 return true; // report success
214 };
215 </code>
216 </pre>
217
218 <p>The <code>ProxyManager\Factory\LazyLoadingValueHolderFactory</code> produces proxies that implement both the <code>ProxyManager\Proxy\ValueHolderInterface</code> and the <code>ProxyManager\Proxy\LazyLoadingInterface</code>.</p>
219
220 <p>At any point in time, you can set a new initializer for the proxy:</p>
221
222 <pre><code class="php">$proxy->setProxyInitializer($initializer);</code></pre>
223
224 <p>In your initializer, you currently <strong>MUST</strong> turn off any further initialization:</p>
225
226 <pre><code class="php">$proxy->setProxyInitializer(null);</code></pre>
227
228 <p>or</p>
229
230 <pre><code class="php">$initializer = null; // if you use the initializer by reference</code></pre>
231 <hr />
232
233 <h3 class="section-title">Triggering Initialization</h3>
234
235 <p>A lazy loading proxy is initialized whenever you access any property or method of it. Any of the following interactions would trigger lazy initialization:</p>
236
237 <pre>
238 <code class="php">
239 // calling a method
240 $proxy->someMethod();
241
242 // reading a property
243 echo $proxy->someProperty;
244
245 // writing a property
246 $proxy->someProperty = 'foo';
247
248 // checking for existence of a property
249 isset($proxy->someProperty);
250
251 // removing a property
252 unset($proxy->someProperty);
253
254 // cloning the entire proxy
255 clone $proxy;
256
257 // serializing the proxy
258 $unserialized = serialize(unserialize($proxy));
259 </code>
260 </pre>
261
262 <p>Remember to call <code>$proxy->setProxyInitializer(null);</code> to disable initialization of your proxy, or it will happen more than once.</p>
263
264
265
266
267
268
269
270
271 <hr />
272
273 <h3 class="section-title">Proxying interfaces</h3>
274
275 <p>You can also generate proxies from an interface FQCN. By proxying an interface, you will only be able to access the methods defined by the interface itself, even if the wrappedObject implements more methods. This will anyway save some memory since the proxy won't contain useless inherited properties.</p>
276
277 <p>Tuning performance for production</p>
278
279 <p>See <a href="production.html">Tuning ProxyManager for Production.</a></p>
280
281
282
283 </main>
284
285 <footer class="site-footer" role="contentinfo">
286 <div class="container">
287 <div class="footer-logos">
288 <ul>
289 <li><a href="index.html">Intro</a> | </li>
290 <li><a href="virtual-proxy.html">Virtual Proxy</a> | </li>
291 <li><a href="null-object.html">Null Objects</a> | </li>
292 <li><a href="ghost-object.html">Ghost Objects</a> | </li>
293 <li><a href="remote-object.html">Remote Object</a> | </li>
294 <li><a href="contributing.html">Contributing</a> | </li>
295 <li><a href="credits.html">Credits</a> | </li>
296 <li><a href="copyright.html">Copyright</a></li>
297 </ul>
298 </div>
299 </div>
300
301 <div class="bcms-clearfix"></div>
302 </footer>
303 <div class="bcms-clearfix"></div>
304 </body>
305 </html>
306