[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/ocramius/proxy-manager/docs/ -> lazy-loading-ghost-object.md (source)

   1  # Lazy Loading Ghost Object Proxies
   2  
   3  A lazy loading ghost object proxy is a ghost proxy that looks exactly like the real instance of the proxied subject,
   4  but which has all properties nulled before initialization.
   5  
   6  ## Lazy loading with the Ghost Object
   7  
   8  In pseudo-code, in userland, [lazy loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) in a ghost object
   9  looks like following:
  10  
  11  ```php
  12  class MyObjectProxy
  13  {
  14      private $initialized = false;
  15      private $name;
  16      private $surname;
  17  
  18      public function doFoo()
  19      {
  20          $this->init();
  21  
  22          // Perform doFoo routine using loaded variables
  23      }
  24  
  25      private function init()
  26      {
  27          if (! $this->initialized) {
  28              $data          = some_logic_that_loads_data();
  29  
  30              $this->name    = $data['name'];
  31              $this->surname = $data['surname'];
  32  
  33              $this->initialized = true;
  34          }
  35      }
  36  }
  37  ```
  38  
  39  Ghost objects work similarly to virtual proxies, but since they don't wrap around a "real" instance of the proxied
  40  subject, they are better suited for representing dataset rows.
  41  
  42  ## When do I use a ghost object?
  43  
  44  You usually need a ghost object in cases where following applies
  45  
  46   * you are building a small data-mapper and want to lazily load data across associations in your object graph
  47   * you want to initialize objects representing rows in a large dataset
  48   * you want to compare instances of lazily initialized objects without the risk of comparing a proxy with a real subject
  49   * you are aware of the internal state of the object and are confident in working with its internals via reflection
  50     or direct property access
  51  
  52  ## Usage examples
  53  
  54  [ProxyManager](https://github.com/Ocramius/ProxyManager) provides a factory that creates lazy loading ghost objects.
  55  To use it, follow these steps:
  56  
  57  First of all, define your object's logic without taking care of lazy loading:
  58  
  59  ```php
  60  namespace MyApp;
  61  
  62  class Customer
  63  {
  64      private $name;
  65      private $surname;
  66  
  67      // just write your business logic or generally logic
  68      // don't worry about how complex this object will be!
  69      // don't code lazy-loading oriented optimizations in here!
  70      public function getName() { return $this->name; }
  71      public function setName($name) { $this->name = (string) $name; }
  72      public function getSurname() { return $this->surname; }
  73      public function setSurname($surname) { $this->surname = (string) $surname; }
  74  }
  75  ```
  76  
  77  Then use the proxy manager to create a ghost object of it.
  78  You will be responsible of setting its state during lazy loading:
  79  
  80  ```php
  81  namespace MyApp;
  82  
  83  use ProxyManager\Factory\LazyLoadingGhostFactory;
  84  use ProxyManager\Proxy\LazyLoadingInterface;
  85  
  86  require_once  __DIR__ . '/vendor/autoload.php';
  87  
  88  $factory     = new LazyLoadingGhostFactory();
  89  $initializer = function (LazyLoadingInterface $proxy, $method, array $parameters, & $initializer) {
  90      $initializer   = null; // disable initialization
  91  
  92      // load data and modify the object here
  93      $proxy->setName('Agent');
  94      $proxy->setSurname('Smith');
  95  
  96      return true; // confirm that initialization occurred correctly
  97  };
  98  
  99  $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).


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1