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