proxy oop pattern in php

41
PROXY PATTERN IN PHP

Upload: marco-pivetta

Post on 29-Nov-2014

4.992 views

Category:

Technology


3 download

DESCRIPTION

An introduction of the Proxy Pattern for PHP Developers. Covers topics such as Lazy loading, Weak References, Smart References, Protection and Remote proxies.

TRANSCRIPT

Page 1: Proxy OOP Pattern in PHP

PROXY PATTERNIN PHP

Page 2: Proxy OOP Pattern in PHP

Doctrine core teamZf2 contributorWasting time on:

OcraDiCompilerOcraServiceManagerOcraCachedViewResolverDoctrine ZF2 ModulesZeffMuAssetManagerKJSencha

Follow @OcramiusFollow @Ocramius

MARCO PIVETTA

Follow Follow @Ocramius@Ocramius

Page 3: Proxy OOP Pattern in PHP

WHAT IS A PROXY?A proxy is generally an object whoseinterface is a layer between us and a

different object with the sameinterface.

Page 4: Proxy OOP Pattern in PHP
Page 5: Proxy OOP Pattern in PHP

Simplified, in PHP

Even if we're not implementing aninterface, the interface of

CustomerProxy is the same as theone of Customer

Page 6: Proxy OOP Pattern in PHP

WHERE TO USE PROXIES?As of the , a proxy can be used inany place where the "proxied" object

can be used.

LSP

Page 7: Proxy OOP Pattern in PHP

WHEN TO USE A PROXY?Lazy loadingRemote objectsSmart reference/Weak referenceProtectionAOPNull object fallback

Page 8: Proxy OOP Pattern in PHP

LAZY LOADINGWe may want to use lazy loading to

avoid IO operations or heavy loadingoperation until really needed

Page 9: Proxy OOP Pattern in PHP

LAZY LOADING PATTERNS1. Virtual Object2. Value Holder3. Ghost Object

Page 10: Proxy OOP Pattern in PHP

VIRTUAL OBJECTAn object whose properties are all setto null, and where each access to the

properties is tracked.

Access triggers lazy loading on theproperty.

Page 11: Proxy OOP Pattern in PHP

VALUE HOLDERAn object that can hold an instance of

the original proxied object, and loads itonly when needed.

Page 12: Proxy OOP Pattern in PHP

GHOST OBJECTAn object whose properties are the

same of the proxied object, but null.

Accessing any method causes loading ofthe properties.

are thisway.

Doctrine Proxies generated

Page 13: Proxy OOP Pattern in PHP

VALUE HOLDER EXAMPLE(1/3)

class Image { public function __construct($path) { $this->image = imagecreatefromjpeg($path); }

public function getSize() { return array(imagesx($this->image), imagesy($this->image)); }}

Page 14: Proxy OOP Pattern in PHP

VALUE HOLDER EXAMPLE(2/3)

class ImageProxy extends Image { protected $image; public function __construct($path) { $this->path = $path; }

private function init() { if ( ! $this->image) { $this->image = new Image($this->path); } }

public function getSize() { $this->init(); return $this->image->getSize(); }}

Page 15: Proxy OOP Pattern in PHP

VALUE HOLDER EXAMPLE(3/3)

$img1 = new ImageProxy('/path/to/image1.jpg');var_dump(memory_get_usage()); // ~200Kb$img2 = new ImageProxy('/path/to/image2.jpg');var_dump(memory_get_usage()); // ~200Kb$img3 = new ImageProxy('/path/to/image3.jpg');var_dump(memory_get_usage()); // ~200Kb

$size1 = $img1->getSize();var_dump(memory_get_usage()); // ~4Mb$size2 = $img2->getSize();var_dump(memory_get_usage()); // ~8Mb

Page 16: Proxy OOP Pattern in PHP

LAZY LOADING PROS/CONSAdvantages

Low memory impactLow overheadEasy to implementUseful to determine object "dirty"status

Dis-advantagesNot optimal for data that is alwaysloadedLazy loading means lazy failing

Page 17: Proxy OOP Pattern in PHP

REMOTE OBJECT

It basically is a specific form of lazyloading

Page 18: Proxy OOP Pattern in PHP

REMOTE OBJECT EXAMPLE(1/3)

class Tweet { protected $data;

public function __construct(array $data) { $this->data = $data; }

public function getText() { return $this->data['text']; }}

Page 19: Proxy OOP Pattern in PHP

REMOTE OBJECT EXAMPLE(2/3)

class TweetProxy extends Tweet { protected $api; protected $tweet; protected $id;

public function __construct(TwitterApi $api, $id) { $this->api = $api; $this->id = $id; } private function init() { if ( ! $this->tweet) { $this->tweet = new Tweet($this->api->get($this->id)); } } public function getText() { $this->init(); return $this->tweet->getText(); }}

Page 20: Proxy OOP Pattern in PHP

REMOTE OBJECT EXAMPLE(3/3)

$tweet = new Tweet(array('text' => 'Proxies in PHP!'));var_dump($tweet->getText()); // 'Proxies in PHP!'

$api = new TwitterApi(/* yadda */); // zf, buzz, etc

$remoteTweet = new TweetProxy($api, 280643708968386560);var_dump($remoteTweet->getText()); // 'Tweet text!'$remoteTweet = new TweetProxy($api, 280643708968386561);var_dump($remoteTweet->getText()); // 'Another text!'

Page 21: Proxy OOP Pattern in PHP

REMOTE OBJECT PROS/CONSAdvantages

Abstraction of a remote objectYou can re-define the proxiedobject's API locally

Dis-advantagesTo use such a proxy, you almostalways need a configured remoteclientRemote objects fail very easily

Page 22: Proxy OOP Pattern in PHP

SMART REFERENCESmart reference can be used to:

swap the proxied object at runtimereference singletons or use internalstatic registriesOptimize memory usage

Page 23: Proxy OOP Pattern in PHP

SMART REFERENCE WITHWEAKREF

Using to save memory onlong-running processesWeakref

class ImageProxy extends Image { // [...] (see previous example) private function init() { if ( ! $this->imageRef || ! $this->imageRef->valid()) { $this->imageRef = new WeakRef(new Image($this->path)); }

return $this->imageRef->get(); }

public function getSize() { return $this->init()->getSize(); }}

Page 24: Proxy OOP Pattern in PHP

SMART REFERENCE WITH AREGISTRY

class ImageProxy extends Image { // [...] (see previous example) private function init() { if (null === $this->image) { $this->image = ImageRegistry::get($this->path); } }

public function getSize() { $this->init(); return $this->image->getSize(); }}

Page 25: Proxy OOP Pattern in PHP

SMART REFERENCEPROS/CONS

Mainly memory usage, but it dependson how you setup your "smart"

reference

Page 26: Proxy OOP Pattern in PHP

PROTECTION PROXYProtection proxy comes into play whenyou want to transparently limit access

to an API through a set of rules(ACL/limits)

Page 27: Proxy OOP Pattern in PHP

PROTECTION PROXY (1/2)class RemoteApiProxy extends RemoteApi { protected $count = 0; public function __construct(RemoteApi $api, $limit) { $this->api = $api; $this->limit = $limit; }

private function count() { if (++$this->count > $this->limit) { throw new RemoteApiLimit('STAHP!'); } }

public function doStuff() { $this->count(); return $this->api->doStuff(); }}

Page 28: Proxy OOP Pattern in PHP

PROTECTION PROXY (2/2)$api = new RemoteApiProxy(new RemoteApi(/* ... */), 50);

while (1) { $api->doStuff(); // RemoteApiLimit exception!}

Page 29: Proxy OOP Pattern in PHP

PROTECTION PROXYPROS/CONS

AdvantagesTransparent filtering or limiting ofaccess to an object

Dis-advantagesModifies proxied object behavior!More like a decorator!

Page 30: Proxy OOP Pattern in PHP

NULL OBJECT FALLBACKPROXY

A null object is an object thatimplements an interface, but produces

no side effects. It replaces null.

Using null objects allows us to workwith the assumption that an object will

always be available, reducing checksagainst null by a lot.

Page 31: Proxy OOP Pattern in PHP

NULL OBJECT FALLBACKPROXY EXAMPLE

class CustomerProxy extends Customer { public function __construct(Db $db, $id) { $this->customer = $db->find($id);

if ( ! $this->customer) { $this->customer = new NullCustomer(); } }

public function doStuff() { return $this->customer->doStuff(); }}

Page 32: Proxy OOP Pattern in PHP

NULL OBJECT FALLBACKPROXY PROS

Performance (with small # ofinstances)Reduced NPaths, therefore code iseasier to test

Page 33: Proxy OOP Pattern in PHP

AOP AND PROXIESProxies basically enable us to have logic

between us and any object, makingAOP easy even when the language

doesn't allow it.

We can use code generation to createon-the-fly proxies with our custom AOP

logic executed pre- and post- anymethod of the proxied object.

Page 34: Proxy OOP Pattern in PHP

AOP EXAMPLES

Becomes:

/** * @AOP\Cache(ttl=3600) */public function doHeavyStuff() { // [...]}

public function doHeavyStuff() { if($cached = $this->cache->get('doHeavyStuff', func_get_args())) { return $cached; }

$return = $this->originalObject->doHeavyStuff(); $this->cache->set($return, 'doHeavyStuff', func_get_args());

return $return;}

Page 35: Proxy OOP Pattern in PHP

IMPLEMENTATION DETAILS INPHP

Page 36: Proxy OOP Pattern in PHP

IMPLEMENTING THE PUBLICAPI

1. The Proxy class MUST extend theproxied class

2. Each of the proxied methods must berewritten

3. Proxies should be serializable4. Proxies should handle public

properties

Page 37: Proxy OOP Pattern in PHP

PUBLIC PROPERTIESPROXYING

class Customer { public $name; public $surname;}

class CustomerProxy extends Customer { public function __construct(Customer $customer) { unset($this->name, $this->surname); $this->customer = $customer; }

public function __set($name, $value) { $this->customer->$name = $value; } public function __get($name) { return $this->customer->$name; } // __isset, __unset}

Page 38: Proxy OOP Pattern in PHP

A COMPLETE GHOST OBJECTIMPLEMENTATION

https://gist.github.com/4038004

Page 39: Proxy OOP Pattern in PHP

SOME USEFUL LIBRARIEShttp://flow.typo3.orghttps://github.com/schmittjoh/cg-libraryhttps://github.com/doctrine/commonhttps://github.com/lisachenko/go-aop-php

Page 41: Proxy OOP Pattern in PHP

QUESTIONS?