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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

lazy-loading-ghost-object.md

Zuletzt modifiziert: 09.10.2024, 12:56 - Dateigröße: 6.43 KiB


001  # Lazy Loading Ghost Object Proxies
002   
003  A lazy loading ghost object proxy is a ghost proxy that looks exactly like the real instance of the proxied subject,
004  but which has all properties nulled before initialization.
005   
006  ## Lazy loading with the Ghost Object
007   
008  In pseudo-code, in userland, [lazy loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) in a ghost object
009  looks like following:
010   
011  ```php
012  class MyObjectProxy
013  {
014      private $initialized = false;
015      private $name;
016      private $surname;
017   
018      public function doFoo()
019      {
020          $this->init();
021   
022          // Perform doFoo routine using loaded variables
023      }
024   
025      private function init()
026      {
027          if (! $this->initialized) {
028              $data          = some_logic_that_loads_data();
029   
030              $this->name    = $data['name'];
031              $this->surname = $data['surname'];
032   
033              $this->initialized = true;
034          }
035      }
036  }
037  ```
038   
039  Ghost objects work similarly to virtual proxies, but since they don't wrap around a "real" instance of the proxied
040  subject, they are better suited for representing dataset rows.
041   
042  ## When do I use a ghost object?
043   
044  You usually need a ghost object in cases where following applies
045   
046   * you are building a small data-mapper and want to lazily load data across associations in your object graph
047   * you want to initialize objects representing rows in a large dataset
048   * you want to compare instances of lazily initialized objects without the risk of comparing a proxy with a real subject
049   * you are aware of the internal state of the object and are confident in working with its internals via reflection
050     or direct property access
051   
052  ## Usage examples
053   
054  [ProxyManager](https://github.com/Ocramius/ProxyManager) provides a factory that creates lazy loading ghost objects.
055  To use it, follow these steps:
056   
057  First of all, define your object's logic without taking care of lazy loading:
058   
059  ```php
060  namespace MyApp;
061   
062  class Customer
063  {
064      private $name;
065      private $surname;
066   
067      // just write your business logic or generally logic
068      // don't worry about how complex this object will be!
069      // don't code lazy-loading oriented optimizations in here!
070      public function getName() { return $this->name; }
071      public function setName($name) { $this->name = (string) $name; }
072      public function getSurname() { return $this->surname; }
073      public function setSurname($surname) { $this->surname = (string) $surname; }
074  }
075  ```
076   
077  Then use the proxy manager to create a ghost object of it.
078  You will be responsible of setting its state during lazy loading:
079   
080  ```php
081  namespace MyApp;
082   
083  use ProxyManager\Factory\LazyLoadingGhostFactory;
084  use ProxyManager\Proxy\LazyLoadingInterface;
085   
086  require_once __DIR__ . '/vendor/autoload.php';
087   
088  $factory     = new LazyLoadingGhostFactory();
089  $initializer = function (LazyLoadingInterface $proxy, $method, array $parameters, & $initializer) {
090      $initializer   = null; // disable initialization
091   
092      // load data and modify the object here
093      $proxy->setName('Agent');
094      $proxy->setSurname('Smith');
095   
096      return true; // confirm that initialization occurred correctly
097  };
098   
099  $instance = $factory->createProxy('MyApp\Customer', $initializer);
100  ```
101   
102  You can now simply use your object as before:
103   
104  ```php
105  // this will just work as before
106  echo $proxy->getName() . ' ' . $proxy->getSurname(); // Agent Smith
107  ```
108   
109  ## Lazy Initialization
110   
111  As you can see, we use a closure to handle lazy initialization of the proxy instance at runtime.
112  The initializer closure signature for ghost objects should be as following:
113   
114  ```php
115  /**
116   * @var object  $proxy         the instance the ghost object proxy that is being initialized
117   * @var string  $method        the name of the method that triggered lazy initialization
118   * @var array   $parameters    an ordered list of parameters passed to the method that
119   *                             triggered initialization, indexed by parameter name
120   * @var Closure $initializer   a reference to the property that is the initializer for the
121   *                             proxy. Set it to null to disable further initialization
122   *
123   * @return bool true on success
124   */
125  $initializer = function ($proxy, $method, $parameters, & $initializer) {};
126  ```
127   
128  The initializer closure should usually be coded like following:
129   
130  ```php
131  $initializer = function ($proxy, $method, $parameters, & $initializer) {
132      $initializer = null; // disable initializer for this proxy instance
133   
134      // modify the object with loaded data
135      $proxy->setFoo(/* ... */);
136      $proxy->setBar(/* ... */);
137   
138      return true; // report success
139  };
140  ```
141   
142  The
143  [`ProxyManager\Factory\LazyLoadingGhostFactory`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Factory/LazyLoadingGhostFactory.php)
144  produces proxies that implement both the
145  [`ProxyManager\Proxy\GhostObjectInterface`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Proxy/GhostObjectInterface.php)
146  and the
147  [`ProxyManager\Proxy\LazyLoadingInterface`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Proxy/LazyLoadingInterface.php).
148   
149  At any point in time, you can set a new initializer for the proxy:
150   
151  ```php
152  $proxy->setProxyInitializer($initializer);
153  ```
154   
155  In your initializer, you **MUST** turn off any further initialization:
156   
157  ```php
158  $proxy->setProxyInitializer(null);
159  ```
160   
161  or
162   
163  ```php
164  $initializer = null; // if you use the initializer passed by reference to the closure
165  ```
166   
167  ## Triggering Initialization
168   
169  A lazy loading ghost object is initialized whenever you access any property or method of it.
170  Any of the following interactions would trigger lazy initialization:
171   
172  ```php
173  // calling a method
174  $proxy->someMethod();
175   
176  // reading a property
177  echo $proxy->someProperty;
178   
179  // writing a property
180  $proxy->someProperty = 'foo';
181   
182  // checking for existence of a property
183  isset($proxy->someProperty);
184   
185  // removing a property
186  unset($proxy->someProperty);
187   
188  // cloning the entire proxy
189  clone $proxy;
190   
191  // serializing the proxy
192  $unserialized = unserialize(serialize($proxy));
193  ```
194   
195  Remember to call `$proxy->setProxyInitializer(null);` to disable initialization of your proxy, or it will happen more
196  than once.
197   
198  ## Proxying interfaces
199   
200  You can also generate proxies from an interface FQCN. By proxying an interface, you will only be able to access the
201  methods defined by the interface itself, even if the `wrappedObject` implements more methods. This will anyway save
202  some memory since the proxy won't contain any properties.
203   
204  ## Tuning performance for production
205   
206  See [Tuning ProxyManager for Production](https://github.com/Ocramius/ProxyManager/blob/master/docs/tuning-for-production.md).
207