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 |
ghost-object.html
001 <!DOCTYPE html>
002 <html class="no-js" id="top">
003 <head>
004 <title>ProxyManager - Ghost object</title>
005
006 <meta name="description" content="A proxyManager write in php" />
007 <meta name="keywords" content="ProxyManager, proxy, manager, ocramius, Marco Pivetta, php, ghost object" />
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 Ghost Object Proxies</h3>
071
072 <p>A lazy loading ghost object proxy is a ghost proxy that looks exactly like the real instance of the proxied subject, but which has all properties nulled before initialization.</p>
073 <hr />
074
075 <h3 class="section-title">Lazy loading with the Ghost Object</h3>
076
077 <p>In pseudo-code, in userland, <a href="http://www.martinfowler.com/eaaCatalog/lazyLoad.html" target="_blank">lazy loading</a> in a ghost object looks like following:</p>
078
079 <pre>
080 <code class="php">
081 class MyObjectProxy
082 {
083 private $initialized = false;
084 private $name;
085 private $surname;
086
087 public function doFoo()
088 {
089 $this->init();
090
091 // Perform doFoo routine using loaded variables
092 }
093
094 private function init()
095 {
096 if (! $this->initialized) {
097 $data = some_logic_that_loads_data();
098
099 $this->name = $data['name'];
100 $this->surname = $data['surname'];
101
102 $this->initialized = true;
103 }
104 }
105 }
106 </code>
107 </pre>
108
109 <p>Ghost objects work similarly to virtual proxies, but since they don't wrap around a "real" instance of the proxied subject, they are better suited for representing dataset rows.</p>
110
111 <hr />
112
113 <h3 class="section-title">When do I use a ghost object?</h3>
114
115 <p>You usually need a ghost object in cases where following applies</p>
116
117 <ul>
118 <li>you are building a small data-mapper and want to lazily load data across associations in your object graph</li>
119 <li>you want to initialize objects representing rows in a large dataset</li>
120 <li>you want to compare instances of lazily initialized objects without the risk of comparing a proxy with a real subject</li>
121 <li>you are aware of the internal state of the object and are confident in working with its internals via reflection or direct property access</li>
122 </ul>
123
124 <hr />
125
126 <h3 class="section-title">Usage examples</h3>
127
128 <p><a href="https://github.com/Ocramius/ProxyManager" target="_blank">ProxyManager</a> provides a factory that creates lazy loading ghost objects. To use it, follow these steps:</p>
129
130 <p>First of all, define your object's logic without taking care of lazy loading:</p>
131
132 <pre>
133 <code class="php">
134 namespace MyApp;
135
136 class Customer
137 {
138 private $name;
139 private $surname;
140
141 // just write your business logic or generally logic
142 // don't worry about how complex this object will be!
143 // don't code lazy-loading oriented optimizations in here!
144 public function getName() { return $this->name; }
145 public function setName($name) { $this->name = (string) $name; }
146 public function getSurname() { return $this->surname; }
147 public function setSurname($surname) { $this->surname = (string) $surname; }
148 }
149 </code>
150 </pre>
151
152 <p>Then use the proxy manager to create a ghost object of it. You will be responsible of setting its state during lazy loading:</p>
153
154 <pre>
155 <code class="php">
156 namespace MyApp;
157
158 use ProxyManager\Factory\LazyLoadingGhostFactory;
159 use ProxyManager\Proxy\LazyLoadingInterface;
160
161 require_once __DIR__ . '/vendor/autoload.php';
162
163 $factory = new LazyLoadingGhostFactory();
164 $initializer = function (LazyLoadingInterface $proxy, $method, array $parameters, & $initializer) {
165 $initializer = null; // disable initialization
166
167 // load data and modify the object here
168 $proxy->setName('Agent');
169 $proxy->setSurname('Smith');
170
171 return true; // confirm that initialization occurred correctly
172 };
173
174 $instance = $factory->createProxy('MyApp\Customer', $initializer);
175 </code>
176 </pre>
177
178 <p>You can now simply use your object as before:</p>
179
180 <pre>
181 <code class="php">
182 // this will just work as before
183 echo $proxy->getName() . ' ' . $proxy->getSurname(); // Agent Smith
184 </code>
185 </pre>
186 <hr />
187
188 <h3 class="section-title">Lazy Initialization</h3>
189
190 <p>As you can see, we use a closure to handle lazy initialization of the proxy instance at runtime. The initializer closure signature for ghost objects should be as following:</p>
191
192 <pre>
193 <code class="php">
194 /**
195 * @var object $proxy the instance the ghost object proxy that is being initialized
196 * @var string $method the name of the method that triggered lazy initialization
197 * @var array $parameters an ordered list of parameters passed to the method that
198 * triggered initialization, indexed by parameter name
199 * @var Closure $initializer a reference to the property that is the initializer for the
200 * proxy. Set it to null to disable further initialization
201 *
202 * @return bool true on success
203 */
204 $initializer = function ($proxy, $method, $parameters, & $initializer) {};
205 </code>
206 </pre>
207
208 <p>The initializer closure should usually be coded like following:</p>
209
210 <pre>
211 <code class="php">
212 $initializer = function ($proxy, $method, $parameters, & $initializer) {
213 $initializer = null; // disable initializer for this proxy instance
214
215 // modify the object with loaded data
216 $proxy->setFoo(/* ... */);
217 $proxy->setBar(/* ... */);
218
219 return true; // report success
220 };
221 </code>
222 </pre>
223
224 <p>The <code>ProxyManager\Factory\LazyLoadingGhostFactory</code> produces proxies that implement both the <code>ProxyManager\Proxy\GhostObjectInterface</code> and the <code>ProxyManager\Proxy\LazyLoadingInterface</code>.</p>
225
226 <p>At any point in time, you can set a new initializer for the proxy:</p>
227
228 <pre>
229 <code class="php">
230 $proxy->setProxyInitializer($initializer);
231 </code>
232 </pre>
233
234 <p>In your initializer, you <strong>MUST</strong> turn off any further initialization:</p>
235
236 <pre>
237 <code class="php">
238 $proxy->setProxyInitializer(null);
239 </code>
240 </pre>
241
242 <p>or</p>
243
244 <pre>
245 <code class="php">
246 $initializer = null; // if you use the initializer passed by reference to the closure
247 </code>
248 </pre>
249 <hr />
250
251 <h3 class="section-title">Triggering Initialization</h3>
252
253 <p>A lazy loading ghost object is initialized whenever you access any property or method of it. Any of the following interactions would trigger lazy initialization:</p>
254
255 <pre>
256 <code class="php">
257 // calling a method
258 $proxy->someMethod();
259
260 // reading a property
261 echo $proxy->someProperty;
262
263 // writing a property
264 $proxy->someProperty = 'foo';
265
266 // checking for existence of a property
267 isset($proxy->someProperty);
268
269 // removing a property
270 unset($proxy->someProperty);
271
272 // cloning the entire proxy
273 clone $proxy;
274
275 // serializing the proxy
276 $unserialized = unserialize(serialize($proxy));
277 </code>
278 </pre>
279
280 <p>Remember to call <code>$proxy->setProxyInitializer(null);</code> to disable initialization of your proxy, or it will happen more than once.</p>
281
282 <hr />
283
284 <h3 class="section-title">Proxying interfaces</h3>
285
286 <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 <code>wrappedObject</code> implements more methods. This will anyway save some memory since the proxy won't contain any properties.</p>
287
288 <p>Tuning performance for production</p>
289
290 <p>See <a href="production.html">Tuning ProxyManager for Production.</a></p>
291
292 </main>
293
294 <footer class="site-footer" role="contentinfo">
295 <div class="container">
296 <div class="footer-logos">
297 <ul>
298 <li><a href="index.html">Intro</a> | </li>
299 <li><a href="virtual-proxy.html">Virtual Proxy</a> | </li>
300 <li><a href="null-object.html">Null Objects</a> | </li>
301 <li><a href="ghost-object.html">Ghost Objects</a> | </li>
302 <li><a href="remote-object.html">Remote Object</a> | </li>
303 <li><a href="contributing.html">Contributing</a> | </li>
304 <li><a href="credits.html">Credits</a> | </li>
305 <li><a href="copyright.html">Copyright</a></li>
306 </ul>
307 </div>
308 </div>
309
310 <div class="bcms-clearfix"></div>
311 </footer>
312 <div class="bcms-clearfix"></div>
313 </body>
314 </html>
315