A little abstraction a bs t r a c t c l a s s Hum a ns { publ i c f unc t i on __c ons t r uc t ( $na m e ) { / *. . . */ } a bs t r a c t publ i c f unc t i on ge nde r ( ) ; publ i c f unc t i on e a t ( ) { / *. . . */ } publ i c f unc t i on s l e e p( ) { / *. . . */ } publ i c f unc t i on wa ke up( ) { / *. . . */ } } c l a s s W om e n e xt e nds Hum a ns { publ i c f unc t i on ge nde r ( ) { r e t ur n ' f e m a l e ' ; } publ i c f unc t i on gi ve Bi r t h( ) { / *. . . */ } } c l a s s M e n e xt e nds Hum a ns { publ i c f unc t i on ge nde r ( ) { r e t ur n ' m a l e ' ; } publ i c f unc t i on s nor e ( ) { / *. . . */ } } Marcus Börger Objects for the Masses 23
A little abstraction a bs t r a c t c l a s s Hum a ns { publ i c f unc t i on __c ons t r uc t ( $na m e ) { / *. . . */ } a bs t r a c t publ i c f unc t i on ge nde r ( ) ; publ i c f unc t i on e a t ( ) { / *. . . */ } publ i c f unc t i on s l e e p( ) { / *. . . */ } publ i c f unc t i on wa ke up( ) { / *. . . */ } } c l a s s W om e n e xt e nds Hum a ns { f i na l publ i c f unc t i on ge nde r ( ) { r e t ur n ' f ' ; } publ i c f unc t i on gi ve Bi r t h( ) { / *. . . */ } } c l a s s M e n e xt e nds Hum a ns { f i na l publ i c f unc t i on ge nde r ( ) { r e t ur n ' m ' ; } publ i c f unc t i on s nor e ( ) { / *. . . */ } } Marcus Börger Objects for the Masses 24
PHP & OOP Marcus Börger Objects for the Masses 25
PHP 4 and OOP ? ¤ Poor Object model � Methods � No visibility � No abstracts, no final � Static without declaration � Properties � No static properties � No constants � Inheritance � No abstract, final inheritance, no interfaces � No prototype checking, no types � Object handling � Copied by value � No destructors Marcus Börger Objects for the Masses 26
ZE2's revamped object model � Objects are referenced by identifiers � Constructors and Destructors � Static members � Constants � Visibility � Interfaces � Final and abstract members � Interceptors � Exceptions � Reflection API � Iterators � Namespaces (5.3) � Closures (5.3) . . . Prototypes (5.4/ 6.0/ never?) Marcus Börger Objects for the Masses 27
Revamped Object Model � PHP 5 has really good OOP support � Better code reuse � Better for team development � Easier to refactor � Some patterns lead to much more efficient code � Fits better in marketing scenarios Marcus Börger Objects for the Masses 28
PHP 5 OOP I n Detail Marcus Börger Objects for the Masses 29
Objects referenced by identifiers � Objects are no longer somewhat special arrays � Objects are no longer copied by default � Objects may be copied using clone/ __clone() c l a s s Obj e c t {}; $obj $ref $dup $obj = ne w Obj e c t ( ) ; Instance 1 Instance 2 $r e f = $obj ; $dup = c l one $obj ; Class Object Marcus Börger Objects for the Masses 30
Constructors and Destructors � Constructors/ Destructors control object lifetime � Constructors may have both new OR old style name � New style constructors are preferred � Constructors must not use inherited protocol � Destructors are called when deleting the last reference � No particular or controllable order during shutdown � Destructors cannot have parameters � Since PHP 5.0.1 destructors can work with resources c l a s s Obj e c t { f unc t i on __c ons t r uc t ( ) {} f unc t i on __de s t r uc t ( ) {} } $obj = ne w Obj e c t ( ) ; uns e t ( $obj ) ; Marcus Börger Objects for the Masses 31
Constructors and Destructors � Parents must be called manually c l a s s Ba s e { f unc t i on __c ons t r uc t ( ) {} f unc t i on __de s t r uc t ( ) {} } c l a s s Obj e c t e xt e nds Ba s e { f unc t i on __c ons t r uc t ( ) { par e nt : : __c ons t r uc t ( ) ; } f unc t i on __de s t r uc t ( ) { par e nt : : __de s t r uc t ( ) ; } } $obj = ne w Obj e c t ( ) ; uns e t ( $obj ) ; Marcus Börger Objects for the Masses 32
Default property values � Properties can have default values � Bound to the class not to the object � Default values cannot be changed but overwritten c l a s s Obj e c t { $obj1 $obj2 va r $pr op = " He l l o\ n" ; } Instance 1 Instance 2 $prop $prop $obj 1 = ne w Obj e c t ; $obj 1- >pr op = " He l l o W or l d\ n" ; Class Object $obj 2 = ne w Obj e c t ; $prop/default e c ho $obj 2- >pr op; / / He l l o Marcus Börger Objects for the Masses 33
Static members � Static methods and properties � Bound to the class not to the object � Only exists once per class rather than per instance � Can be initialized $obj1 $obj2 c l a s s Obj e c t { Instance 1 Instance 2 va r $pr op; $prop $prop s t at i c $s t a t = " Hel l o\ n" ; s t at i c f unc t i on t es t ( ) { e c ho s e l f : : $s t a t ; } Class Object } $stat Obj e c t : : t e s t ( ) ; $obj 1 = ne w Obj e c t ; $obj 2 = ne w Obj e c t ; Marcus Börger Objects for the Masses 34
Pseudo constants � shows the current class name __CLASS__ � __M ETH O D__ shows class and method or function � references the class itself s e l f � par e nt references the parent class � $t hi s references the object itself c l a s s Ba s e { s t a t i c f unc t i on Show( ) { e c ho __FI LE__. ' ( ' . __LI NE__. ' ) : ' . __M ETHOD__. " \ n" ; } } c l a s s Obj e c t e xt e nds Ba s e { s t a t i c f unc t i on Us e ( ) { Se l f : : Show( ) ; Pa r e nt : : Show( ) ; } s t a t i c f unc t i on Show( ) { e c ho __FI LE__. ' ( ' . __LI NE__. ' ) : ' . __M ETHOD__. " \ n" ; } } Marcus Börger Objects for the Masses 35
Visibility � Controlling member visibility / Information hiding � A derived class doesn't know parents private m embers � An inherited protected member can be made public c l a s s Ba s e { publ i c $a ; Derived pr ot e c t e d $b; Base pr i vat e $c ; $a } $b c l a s s De r i ve d e xt e nds Ba s e { $c publ i c $a ; publ i c $b; $a pr i vat e $c ; $b } $c Base::$c Marcus Börger Objects for the Masses 36
Constructor visibility � A protected constructor prevents instantiation c l a s s Ba s e { pr ot e c t e d f unc t i on __c ons t r uc t ( ) { } } c l a s s De r i ve d e xt e nds Ba s e { / / c ons t r uc t or i s s t i l l pr ot e c t e d s t a t i c f unc t i on ge t Ba s e ( ) { r e t ur n ne w Ba s e ; / / Fa c t or y pa t t e r n } } c l a s s Thr e e e xt e nds De r i ve d { publ i c f unc t i on __c ons t r uc t ( ) { } } Marcus Börger Objects for the Masses 37
The Singleton pattern � Sometimes you want only a single instance of aclass to ever exist. � DB connections � An object representing the user or connection. c l a s s Si ngl e t on { s t a t i c pr i va t e $i ns t a nc e ; pr ot e c t e d f unc t i on __c ons t r uc t ( ) {} f i na l pr i va t e f unc t i on __c l one ( ) {} s t a t i c f unc t i on ge t I ns t a nc e ( ) { i f ( ! s e l f : : $i ns t a nc e ) s e l f : : $i ns t a nc e = ne w Si ngl e t on( ) ; r e t ur n s e l f : : $i ns t a nc e ; } } $a = Si ngl e t on: : ge t I ns t a nc e ( ) ; $a - >i d = 1; $b = Si ngl e t on: : ge t I ns t a nc e ( ) ; pr i nt $b- >i d. " \ n" ; Marcus Börger Objects for the Masses 38
Constants � Constants are read only static properties � Constants are always public c l a s s Ba s e { c ons t gr e e t i ng = " He l l o\ n" ; } c l a s s De r vi e d e xt e nds Ba s e { c ons t gr e e t i ng = " He l l o W or l d\ n" ; s t a t i c f unc t i on f unc ( ) { e c ho pa r e nt : : gr e e t i ng; } } e c ho Ba s e : : gr e e t i ng; e c ho De r i ve d: : gr e e t i ng; De r i ve d: : f unc ( ) ; Marcus Börger Objects for the Masses 39
Abstract members � Methods can be abstract � They don’t have a body � A class with an abstract method must be abstract � Classes can be made abstract � The class cannot be instantiated � Properties cannot be made abstract abs t r ac t c l a s s Ba s e { abs t r ac t f unc t i on no_body( ) ; } c l a s s De r i ve d e xt e nds Ba s e { f unc t i on no_body( ) { e c ho " Body\ n" ; } } Marcus Börger Objects for the Masses 40
Final members � Methods can be final � They cannot be overwritten � They are class invariants � Classes can be final � They cannot be inherited c l a s s Ba s e { f i nal f unc t i on i nva r i a nt ( ) { e c ho " He l l o\ n" ; } } c l a s s De r i ve d e xt e nds Ba s e { } f i nal c l a s s Le a f e xt e nds De r i ve d { } Marcus Börger Objects for the Masses 41
Different Object same behavior � Often different objects have the same interface without having the same base class c l a s s Li ne { f unc t i on dr a w( ) {}; } c l a s s Pol ygon { pr ot e c t e d $l i ne s ; f unc t i on dr a w( ) { Line Ellipse f or e a c h( $t hi s - >l i ne s a s $l i ne) $l i ne - >dr a w( ) ; } } $lines c l a s s Re c t a ngl e e xt e nds Pol ygon { } Circle Polygon c l a s s El l i ps e { f unc t i on dr a w( ) {}; } c l a s s Ci r c l e ext e nds El l i ps e { f unc t i on dr a w( ) { pa r e nt : : dr a w( ) ; Rectangle } } Marcus Börger Objects for the Masses 42
Interfaces � Interfaces describe an abstract class protocol � Classes may inherit multiple Interfaces i nt e r f a c e Dr a wa bl e { f unc t i on dr a w( ) ; } Drawable c l a s s Li ne i m pl e m e nt s Dr a wa bl e { f unc t i on dr a w( ) {}; } c l a s s Pol ygon i m pl e m e nt s Dr a wa bl e { pr ot e c t e d $l i ne s ; f unc t i on dr a w( ) { Line Ellipse f or e a c h( $t hi s - >l i ne s a s $l i ne) $l i ne - >dr a w( ) ; } } $lines c l a s s Re c t a ngl e e xt e nds Pol ygon { } Circle Polygon c l a s s El l i ps e i m pl e m e nt s Dr a wa bl e { f unc t i on dr a w( ) {}; } c l a s s Ci r c l e ext e nds El l i ps e { f unc t i on dr a w( ) { pa r e nt : : dr a w( ) ; Rectangle } } Marcus Börger Objects for the Masses 43
Property kinds � Declared properties � May have a default value � Can have selected visibility � Implicit public properties � Declared by simply using them in ANY method � Virtual properties � Handled by interceptor methods � Static properties � Bound to the class rather than to the instance Marcus Börger Objects for the Masses 44
Object to String conversion � __toString(): semi-automatic object to string conversion with echo and print (automatic starting with 5.2) c l a s s Obj e c t { f unc t i on __t oSt r i ng ( ) { r e t ur n ' Obj e c t a s s t r i ng' ; } } $o = ne w Obj e c t ; e c ho $o; / / doe s c a l l __t oSt r i ng $s t r = ( s t r i ng) $o; / / doe s c a l l __t oSt r i ng Marcus Börger Objects for the Masses 45
Interceptors � Allow to dynamically handle non class members � Lazy initialization of properties � Simulating Object aggregation and Multiple inheritance c l a s s Obj e c t { pr ot e c t e d $vi r t ua l = a r r a y( ) ; f unc t i on __ge t ( $na m e ) { r e t ur n @ $t hi s - >vi r t ua l [ $na m e ] ; } f unc t i on __s e t ( $na m e , $va l ue ) { $t hi s - >vi r t ua l [ $na m e ] = $va l ue ; } f unc t i on __uns e t ( $na m e ) { uns e t ( $t hi s - >vi r t ua l [ $na m e ] ) ; } f unc t i on __i s s e t ( $na m e ) { r e t ur n i s s e t ( $t hi s - >vi r t ua l [ $na m e ] ) ; } f unc t i on __c al l ( $f unc , $pa r a m s ) { e c ho ' Coul d not c a l l ' . __CLASS__ . ' : : ' . $f unc . " \ n" ; } } Marcus Börger Objects for the Masses 46
Typehinting � PHP 5 allows to easily force a type of a parameter � PHP does not allow NULL for typehints � Typehints must be inherited as given in base class � PHP 5.1 offers typehinting with arrays � PHP 5.2 offers optional typehinted parameters (= NULL) c l a s s Obj e c t { publ i c f unc t i on c om pa r e ( Obj e c t $ot he r ) { / / Som e c ode he r e } publ i c f unc t i on c om pa r e 2( $ot he r ) { i f ( i s _nul l ( $ot he r ) | | $ot he r i ns t a nc e of Obj e c t ) { / / Som e c ode he r e } } } Marcus Börger Objects for the Masses 47
Class Design � It is important to think about your class hierarchy � Avoid very deep or broad inheritance graphs � PHP only supports is-a and has-a relations Tires Bicycle Vehicle Engine Car Bus Truck Diesel Gasoline Tank Turbine Plane Marcus Börger Objects for the Masses 48
Too Strict or too Weak? � PHP tries to prevent you from doing some errors � You are bound to keep inherited signatures � You cannot change from ref to non-ref return � Yet PHP allows absolute flexibility � Just do not define a signature � Warning: This is extrem ely error prone Marcus Börger Objects for the Masses 49
Dynam ic Class Loading Marcus Börger Objects for the Masses 50
Dynamic class loading � � __a ut ol oa d( ) is good when you're alone __a ut ol oa d( ) is good � Requires a single file for each class � Only load class files when necessary � No need to parse/ compile unneeded classes � No need to check which class files to load � Additional user space code N Only one single loader model is possible Marcus Börger Objects for the Masses 51
__a ut ol oa d & r e qui r e _onc e � St or e t he c l a s s l oa de r i n a n i nc l ude f i l e � I n e a c h s c r i pt : r e qui r e _onc e ( ' <pa t h>/ a ut ol oa d. i nc ' ) � Us e I NI opt i on: a ut o_pr e pe nd_f i l e =<pa t h>/ a ut ol oa d. i nc <? php f unc t i on __a ut ol oa d( $c l a s s _na m e ) { r e qui r e _onc e ( di r na m e ( __FI LE__) . ' / ' . $c l a s s _na m e . ' . p5c ' ) ; } ? > Marcus Börger Objects for the Masses 52
SPL's class loading � Supports fast default implementation � Look into path's specified by INI option include_path � Look for specified file extensions (.inc, .php) � Ability to register multiple user defined loaders � Overwrites ZEND engine's __autoload() cache � You need to register __autoload if using spl's autoload <? php s pl _a ut ol oa d_r e gi s t e r ( ' s pl _a ut ol oa d' ) ; i f ( f unc t i on_e xi s t s ( ' __a ut ol oa d' ) ) { s pl _a ut ol oa d_r e gi s t e r ( ' __a ut ol oa d' ) ; } ? > Marcus Börger Objects for the Masses 53
SPL's class loading � s pl _a ut ol oa d( $c l a s s _na m e , $e xt e ns i ons =NULL) Load a class from a file in include path Fast C code implementation � s pl _a ut ol oa d_e xt e ns i ons ( $e xt e ns i ons =NULL) Get or set filename extensions � s pl _a ut ol oa d_r e gi s t e r ( $l oa de r _f unc t i on) Register a single loader function � s pl _a ut ol oa d_unr e gi s t e r ( $l oa de r _f unc t i on) Unregister a single loader function � s pl _a ut ol oa d_f unc t i ons ( ) List all registered loader functions � s pl _a ut ol oa d_c a l l ( $c l a s s _na m e ) Load a class through registered class loaders Uses s pl _a ut ol oa d( ) as fallback Marcus Börger Objects for the Masses 54
Exceptions Marcus Börger Objects for the Masses 55
Exceptions � Respect these rules 1. Exceptions are exceptions 2. Never use exceptions for control flow 3. Never ever use exceptions for param eter passing <? php t r y { / / your c ode t hr ow ne w Exc e pt i on( ) ; } c at c h ( Exc e pt i on $e ) { / / e xc e pt i on ha ndl i ng } ? > Marcus Börger Objects for the Masses 56
Exception specialization � Exceptions should be specialized � Exceptions should inherit built in class exception c l a s s Your Exc e pt i on e xt e nds Exc e pt i on { } t r y { / / your c ode t hr ow ne w Your Exc e pt i on( ) ; } c a t c h ( Your Exc e pt i on $e ) { / / e xc e pt i on ha ndl i ng } c a t c h ( Exc e pt i on $e ) { / / e xc e pt i on ha ndl i ng } Marcus Börger Objects for the Masses 57
Exception specialization � Exception blocks can be nested � Exceptions can be re thrown c l a s s Your Exc e pt i on e xt e nds Exc e pt i on { } t r y { t r y { / / your c ode t hr ow ne w Your Exc e pt i on( ) ; } c a t c h ( Your Exc e pt i on $e ) { / / e xc e pt i on ha ndl i ng t hr ow $e ; } c a t c h ( Exc e pt i on $e ) { / / e xc e pt i on ha ndl i ng } } c a t c h ( Your Exc e pt i on $e ) { / / e xc e pt i on ha ndl i ng } Marcus Börger Objects for the Masses 58
Practical use of exceptions � Constructor failure � Converting errors/ warnings to exceptions � Simplify error handling � Provide additional error information by tagging Marcus Börger Objects for the Masses 59
Constructor failure � In PHP 4.4 you would simply uns e t ( $t hi s ) � Provide an argument to receive the error condition <? php c l a s s Obj e c t { f unc t i on __c ons t r uc t ( &$f a i l ur e ) / / " Obj e c t " i n PHP 4 { $f a i l ur e = t r ue ; } } $e r r or = f a l s e ; $o = ne w Obj e c t ( $e r r or ) ; i f ( ! $e r r or ) { / / e r r or ha ndl i ng, NOTE: t he obj e c t wa s c ons t r uc t e d uns e t ( $o) ; } ? > Marcus Börger Objects for the Masses 60
Constructor failure � In 5 constructors do not return the created object � Exceptions allow to handle failed constructors <? php c l a s s Obj e c t { f unc t i on __c ons t r uc t ( ) { t hr ow ne w Exc e pt i on; } } t r y { $o = ne w Obj e c t ; } c a t c h ( Exc e pt i on $e ) { e c ho " Obj e c t c oul d not be i ns t a nt i a t e d\ n" ; } ? > Marcus Börger Objects for the Masses 61
Convert Errors to Exceptions � Implementing PHP 5.1 class ErrorException <? php i f ( ! c l a s s _e xi s t s ( ' Er r or Exc e pt i on' , f a l s e ) ) { c l a s s Er r or Exc e pt i on e xt e nds Exc e pt i on { pr ot e c t e d $s e ve r i t y; f unc t i on __c ons t r uc t ( $m s g, $c ode , $e r r no, $f i l e , $l i ne ) { pa r e nt : : __c ons t r uc t ( $m s g, $c ode ) ; $t hi s - >s e ve r i t y = $e r r no; $t hi s - >f i l e = $f i l e ; $t hi s - >l i ne = $l i ne ; } f unc t i on ge t Se ve r i t y( ) { r e t ur n $t hi s - >s e ve r i t y; } } } ? > Marcus Börger Objects for the Masses 62
Convert Errors to Exceptions � Implementing the error handler <? php f unc t i on Er r or s ToExc e pt i ons ( $e r r no, $m s g, $f i l e , $l i ne ) { t hr ow ne w Er r or Exc e pt i on( $m s g, 0, $e r r no, $f i l e , $l i ne ) ; } s e t _e r r or _ha ndl e r ( ' Er r or s ToExc e pt i ons ' ) ; ? > Marcus Börger Objects for the Masses 63
Simplify error handling � Typical database access code contains lots of if's <ht m l ><body> <? php $ok = f a l s e ; $db = ne w PDO( ' CONNECTI ON' ) ; i f ( $db) { $r e s = $db- >que r y( ' SELECT da t a ' ) ; i f ( $r e s ) { $r e s 2 = $db- >que r y( ' SELECT ot he r ' ) ; i f ( $r e s 2) { / / ha ndl e da t a $ok = t r ue ; / / onl y i f a l l we nt ok } } } i f ( ! $ok) e c ho ' <h1>Se r vi c e c ur r e nt l y una va i l a bl e </ h1>' ; ? > </ body></ ht m l > Marcus Börger Objects for the Masses 64
Simplify error handling � Trade code simplicity with a new complexity <ht m l ><body> <? php t r y { $db = ne w PDO( ' CONNECTI ON' ) ; $db- >s e t At t r i but e ( PDO: : ATTR_ERRM ODE, PDO: : ERRM ODE_EXCEPTI ON) ; $r e s = $db- >que r y( ' SELECT da t a ' ) ; $r e s 2 = $db- >que r y( ' SELECT ot he r ' ) ; / / ha ndl e da t a } c a t c h ( Exc e pt i on $e ) { e c ho ' <h1>Se r vi c e c ur r e nt l y una va i l a bl e </ h1>' ; e r r or _l og( $e - >ge t M e s s a ge ( ) ) ; } ? > </ body></ ht m l > Marcus Börger Objects for the Masses 65
SPL Exceptions � SPL provides a standard set of exceptions � Class Exception must be the root of all exceptions Marcus Börger Objects for the Masses 66
General distinguishing � Logi c Exc e pt i on Ł Anything that could have been detected at compile time, during application design or by the good old technology: "look closely" � Runt i m e Exc e pt i on Ł Anything that is unexpected during runtime Ł Base Exception for all database extensions Marcus Börger Objects for the Masses 67
LogicException � Function not found or similar Ba dM e t hodCa l l Exc e pt i on � Value not in allowed domain � Argument not valid � Length exceeded � Some index is out of range Marcus Börger Objects for the Masses 68
RunTimeException � An actual value is out of bounds � Buffer or other overflow situation � Value outside expected range � Buffer or other underflow situation � Any other unexpected values Marcus Börger Objects for the Masses 69
Overloading __call � If using __call, ensure only valid calls are made a bs t r a c t c l a s s M yI t e r a t or W r a ppe r i m pl e m e nt s I t e r a t or { f unc t i on __c ons t r uc t ( I t e r a t or $i t ) { Compile-Time: $t hi s - >i t = $i t ; } Error in design f unc t i on __c a l l ( $f unc , $a r gs ) { $c a l l e e = a r r a y( $t hi s - >i t , $f unc ) ; i f ( ! i s _c a l l a bl e ( $c a l l e e ) ) { t hr ow ne w Ba dM e t hodCa l l Exc e pt i on( ) ; } r e t ur n c a l l _us e r _f unc _a r r a y( $c a l l e e , $a r gs ) ; } } Marcus Börger Objects for the Masses 70
Interfaces and __call � Interface functions cannot be handled by __call � Either mark the class abstract... a bs t r a c t c l a s s M yI t e r a t or W r a ppe r i m pl e m e nt s I t e r a t or { I nt e r f a c e I t e r a t or { f unc t i on __c ons t r uc t ( I t e r a t or $i t ) f unc t i on r e wi nd( ) ; { f unc t i on va l i d( ) ; $t hi s - >i t = $i t ; f unc t i on c ur r e nt ( ) ; } f unc t i on __c a l l ( $f unc , $a r gs ) f unc t i on ke y( ) ; { f unc t i on ne xt ( ) ; $c a l l e e = a r r a y( $t hi s - >i t , $f unc ) ; } i f ( ! i s _c a l l a bl e ( $c a l l e e ) ) { t hr ow ne w Ba dM e t hodCa l l Exc e pt i on( ) ; } r e t ur n c a l l _us e r _f unc _a r r a y( $c a l l e e , $a r gs ) ; } } Marcus Börger Objects for the Masses 71
Interfaces and __call � Interface functions cannot be handled by __call � ...or provide the functions (here as proxy/ forward) c l a s s M yI t e r a t or W r a ppe r i m pl e m e nt s I t e r a t or { I nt e r f a c e I t e r a t or { f unc t i on __c ons t r uc t ( I t e r a t or $i t ) f unc t i on r e wi nd( ) ; { f unc t i on va l i d( ) ; $t hi s - >i t = $i t ; f unc t i on c ur r e nt ( ) ; } f unc t i on __c a l l ( $f unc , $a r gs ) f unc t i on ke y( ) ; { f unc t i on ne xt ( ) ; $c a l l e e = a r r a y( $t hi s - >i t , $f unc ) ; } i f ( ! i s _c a l l a bl e ( $c a l l e e ) ) { t hr ow ne w Ba dM e t hodCa l l Exc e pt i on( ) ; } r e t ur n c a l l _us e r _f unc _a r r a y( $c a l l e e , $a r gs ) ; } f unc t i on r e wi nd( ) { $t hi s - >i t - >r e wi nd( ) ; } f unc t i on va l i d( ) { r e t ur n $t hi s - >i t - >va l i d( ) ; } f unc t i on c ur r e nt ( ) { r e t ur n $t hi s - >i t - >c ur r e nt ( ) ; } f unc t i on ke y( ) { r e t ur n $t hi s - >i t - >ke y( ) ; } f unc t i on ne xt ( ) { $t hi s - >i t - >ne xt ( ) ; } } Marcus Börger Objects for the Masses 72
Expecting formatted data � Opening a file for reading Run-Time: File might not be accessible or exist $f o = ne w Spl Fi l e Obj e c t ( $f i l e ) ; $f o- >s e t Fl a gs ( Spl Fi l e Obj e c t : : DROP_NEW LI NE) ; $da t a = a r r a y( ) ; Marcus Börger Objects for the Masses 73
Expecting formatted data � Reading a formatted file line by line Run-Time: File might not be accessible or exist $f o = ne w Spl Fi l e Obj e c t ( $f i l e ) ; $f o- >s e t Fl a gs ( Spl Fi l e Obj e c t : : DROP_NEW LI NE) ; $da t a = a r r a y( ) ; f or e a c h( $f o a s $l ) { i f ( / *** CHECK DATA ***/ ) { t hr ow ne w Ex c e pt i on ( ) ; Run-Time: } data is different for $da t a [ ] = $l ; every execution } � ! pr e g_m a t c h( $r e ge x, $l ) Une xpe c t Va l ue Exc e pt i on � c ount ( $l =s pl i t ( ' , ' , $l ) ) ! = 3 Ra nge Exc e pt i on � c ount ( $da t a ) > 100 Ove r f l owExc e pt i on Marcus Börger Objects for the Masses 74
Expecting formatted data � Cehcking data after pre-processing Run-Time: Filemight not be accessible or exist $f o = ne w Spl Fi l e Obj e c t ( $f i l e ) ; $f o- >s e t Fl a gs ( Spl Fi l e Obj e c t : : DROP_NEW LI NE) ; $da t a = a r r a y( ) ; f or e a c h( $f o a s $l ) { i f ( ! pr e g_m a t c h( ' / \ d, \ d/ ' , $l ) ) { t hr ow ne w Une xpe c t e dVa l ue Exc e pt i on( ) ; Run-Time: } data is different for $da t a [ ] = $l ; every execution } / / Che c ks a f t e r t he f i l e wa s r e a d e nt i r e l y � i f ( c ount ( $da t a ) < 10) t hr ow ne w Unde r f l owExc e pt i on( ) ; � i f ( c ount ( $da t a ) > 99) t hr ow ne w Ove r f l owExc e pt i on( ) ; � i f ( c ount ( $da t a ) < 10 | | c ount ( $da t a ) > 99) t hr ow ne w Out Of Bounds Exc e pt i on( ) ; Marcus Börger Objects for the Masses 75
Expecting formatted data � Processing pre-checked data Run-Time: File might not be accessible or exist $f o = ne w Spl Fi l e Obj e c t ( $f i l e ) ; $f o- >s e t Fl a gs ( Spl Fi l e Obj e c t : : DROP_NEW LI NE) ; $da t a = a r r a y( ) ; f or e a c h( $f o a s $l ) { i f ( ! pr e g_m a t c h( ' / \ d, \ d/ ' , $l ) ) { t hr ow ne w Une xpe c t e dVa l ue Exc e pt i on( ) ; Run-Time: } data is different for $da t a [ ] = $l ; every execution } i f ( c ount ( $da t a ) < 10) t hr ow ne w Unde r f l owExc e pt i on( ) ; / / m a ybe m or e pr e c e s s i ng c ode f or e a c h( $da t a a s & $v) { Compile-Time: i f ( c ount ( $v) == 2) { exception signals t hr ow ne w Dom a i nExc e pt i on( ) ; failed precondition } $v = $v[ 0] * $v[ 1] ; } Marcus Börger Objects for the Masses 76
Reflection Marcus Börger Objects for the Masses 77
Reflection API � Can reflect nearly all aspects of your PHP code � Functions � Classes, Methods, Properties � Extensions c l a s s Foo { publ i c $pr op; f unc t i on Func ( $na m e ) { e c ho " He l l o $na m e " ; } } Re f l e c t i onCl a s s : : e xpor t ( ' Foo' ) ; Re f l e c t i onObj e c t : : e xpor t ( ne w Foo) ; Re f l e c t i onM e t hod: : e xpor t ( ' Foo' , ' f unc ' ) ; Re f l e c t i onPr ope r t y: : e xpor t ( ' Foo' , ' pr op' ) ; Re f l e c t i onExt e ns i on: : e xpor t ( ' s t a nda r d' ) ; Marcus Börger Objects for the Masses 78
Dynamic object creation � Reflection allows dynamic object creation c l a s s Te s t { f unc t i on __c ons t r uc t ( $x, $y = NULL) { $t hi s - >x = $x; $t hi s - >y = $y; } } f unc t i on ne w_obj e c t _a r r a y( $c l s , $a r gs = NULL) { r e t ur n c a l l _us e r _f unc _a r r a y( a r r a y( ne w Re f l e c t i onCl a s s ( $c l s ) , ' ne wI ns t a nc e ' ) , $a r gs ) ; } ne w_obj e c t _a r r a y( ' s t dCl a s s ' ) ; ne w_obj e c t _a r r a y( ' Te s t ' , a r r a y( 1) ) ; ne w_obj e c t _a r r a y( ' Te s t ' , a r r a y( 1, 2) ) ; Marcus Börger Objects for the Masses 79
Built-in I nterfaces Marcus Börger Objects for the Masses 80
Built-in Interfaces � PHP 5 contains built-in interfaces that allow you to change the way the engine treats objects. � Ar r a yAc c e s s � I t e r a t or � I t e r a t or Aggr e ga t e � Built-in extension SPL provides more I nterfaces and Classes � Ar r a yObj e c t , Ar r a yI t e r a t or � Fi l t e r I t e r a t or � Re c ur s i ve I t e r a t or � Use CLI: php - - r e SPL php - - r c Ar r a yAc c e s s Marcus Börger Objects for the Masses 81
ArrayAccess � Allows for creating objects that can be transparently accessed by array syntax. � When combined with the iterator interface, it allows for creating ‘arrays with special properties’. i nt e r f a c e Ar r a yAc c e s s { / / @ r e t ur n whe t he r $of f s e t i s va l i d ( t r ue / f a l s e ) f unc t i on of f s e t Exi s t s ( $of f s e t ) ; / / @ r e t ur n t he va l ue a s s oc i a t e d wi t h $of f s e t f unc t i on of f s e t Ge t ( $of f s e t ) ; / / a s s oc i a t e $va l ue wi t h $of f s e t ( s t or e t he da t a ) f unc t i on of f s e t Se t ( $of f s e t , $va l ue ) ; / / uns e t t he da t a a s s oc i a t e d wi t h $of f s e t f unc t i on of f s e t Uns e t ( $of f s e t ) ; } Marcus Börger Objects for the Masses 82
ArrayAccess � ArrayAccess does not allow references (the following is an error) c l a s s M yAr r a y e xt e nds Ar r a yAc c e s s { f unc t i on & of f s e t Ge t ( $of f s e t ) { / * . . . */ } f unc t i on of f s e t Se t ( $of f s e t , & $va l ue ) { / * . . . */ } f unc t i on of f s e t Exi s t s ( $of f s e t ) { / * . . . */ } f unc t i on of f s e t Uns e t ( $of f s e t ) { / * . . . */ } } Marcus Börger Objects for the Masses 83
ArrayAccess Example � We want to create variables which can be shared between processes. � We will set up interception so that access attempts on the variable are actually performed through a DBM file. Marcus Börger Objects for the Masses 84
Binding Access to a DBM <? php c l a s s Dba Ac c e s s i m pl e m e nt s Ar r a yAc c e s s { pr ot e c t e d $db = NULL; f unc t i on __c ons t r uc t ( $f i l e , $ha ndl e r ) { i f ( ! $t hi s - >db = dba _ope n( $f i l e , ' c d' , $ha ndl e r ) ) t hr ow ne w e xc e pt i on( ' Coul d not ope n f i l e ' . $f i l e ) ; } f unc t i on __de s t r uc t ( ) { dba _c l os e ( $t hi s - >db) ; } f unc t i on of f s e t Exi s t s ( $of f s e t ) { r e t ur n dba _e xi s t s ( $of f s e t , $t hi s - >db) ; } f unc t i on of f s e t Ge t ( $of f s e t ) { r e t ur n dba _f e t c h( $of f s e t , $t hi s - >db) ; } f unc t i on of f s e t Se t ( $of f s e t , $va l ue ) { r e t ur n dba _r e pl a c e ( $of f s e t , $va l ue , $t hi s - >db) ; } f unc t i on of f s e t Uns e t ( $of f s e t ) { r e t ur n dba _de l e t e ( $of f s e t , $t hi s - >db) ; } } ? > Marcus Börger Objects for the Masses 85
A Trivial Example <? php i f ( ! c l a s s _e xi s t s ( ' Dba Re a de r ' , f a l s e ) ) { r e qui r e _onc e ‘ dba de a de r . i nc ’ ; } $_SHARED = ne w Dba Ac c e s s ( ' / t m p/ . c ount e r ' , ' f l a t f i l e ' ) ; $_SHARED[ ' c ount e r ' ] += 1; pr i nt f ( " PI D: % d\ nCOUNTER: % d\ n" , ge t m ypi d( ) , $_SHARED[ ' c ount e r ' ] ) ; ? > Marcus Börger Objects for the Masses 86
Iterators � Normal objects behave like arrays when used with the foreach construct � Specialized I terator objects can be iterated differently <? php c l a s s Obj e c t { publ i c $pr op1 = " He l l o " ; publ i c $pr op2 = " W or l d\ n" ; } f or e a c h( ne w Obj e c t a s $pr op) { e c ho $pr op; } ? > Marcus Börger Objects for the Masses 87
What are Iterators � Iterators are a concept to iterate anything that contains other things. � Iterators allow to encapsulate algorithms Marcus Börger Objects for the Masses 88
What are Iterators � Iterators are a concept to iterate anything that contains other things. Examples: � Values and Keys in an array Ar r a yObj e c t , Ar r a yI t e r a t or � Text lines in a file Spl Fi l e Obj e c t � Files in a directory [ Re c ur s i ve ] Di r e c t or yI t e r a t or � XML Elements or Attributes ext: SimpleXML, DOM � Database query results ext: PDO, SQLite, MySQLi � Dates in a calendar range PECL/ date (?) � Bits in an image ? � Iterators allow to encapsulate algorithms Marcus Börger Objects for the Masses 89
What are Iterators � Iterators are a concept to iterate anything that contains other things. Examples: � Values and Keys in an array Ar r a yObj e c t , Ar r a yI t e r a t or � Text lines in a file Spl Fi l e Obj e c t � Files in a directory [ Re c ur s i ve ] Di r e c t or yI t e r a t or � XML Elements or Attributes ext: SimpleXML, DOM � Database query results ext: PDO, SQLite, MySQLi � Dates in a calendar range PECL/ date (?) � Bits in an image ? � Iterators allow to encapsulate algorithms � Classes and Interfaces provided by SPL: Appe ndI t e r a t or , Ca c hi ngI t e r a t or , Li m i t I t e r a t or , Fi l t e r I t e r a t or , Em pt yI t e r a t or , I nf i ni t e I t e r a t or , NoRe wi ndI t e r a t or , Out e r I t e r a t or , Pa r e nt I t e r a t or , Re c ur s i ve I t e r a t or , Re c ur s i ve I t e r a t or I t e r a t or , Se e ka bl e I t e r a t or , Spl Fi l e Obj e c t , . . . Marcus Börger Objects for the Masses 90
Array vs. Iterator � An array in PHP $a r = a r r a y( ) � can be rewound: r e s e t ( $a r ) � is valid unless it's key is NULL: ! i s _nul l ( ke y( $a r ) ) � have current values: c ur r e nt ( $a r ) � have keys: ke y( $a r ) � can be forwarded: ne xt ( $a r ) � Something that is traversable $i t = ne w I t e r a t or ; � m ay know how to be rewound: $i t - >r e wi nd( ) ( doe s not r e t ur n t he e l e m e nt ) � should know if there is a value: $i t - >va l i d( ) � m ay have a current value: $i t - >c ur r e nt ( ) � m ay have a key: $i t - >ke y( ) ( m a y r e t ur n NULL a t a ny t i m e ) � can forward to its next element: $i t - >ne xt () Marcus Börger Objects for the Masses 91
The big difference � Arrays � require memory for all elements � allow to access any element directly � I terators � only know one element at a time � only require mem ory for the current elem ent � forward access only � Access done by m ethod calls � Containers � require memory for all elements � allow to access any element directly � can create external Iterators or are internal Iterators Marcus Börger Objects for the Masses 92
The basic concepts � Iterators can be internal or external also referred to as active or passive � An internal iterator modifies the object itself � An external iterator points to another object without modifying it � PHP always uses external iterators at engine-level � Iterators may iterate over other iterators Marcus Börger Objects for the Masses 93
PHP Iterators � Anything that can be iterated implements Tr ave r s abl e � Objects implementing Tr ave r s abl e can be used in f or e ac h � User classes cannot implement Tr ave r s abl e � I t e r at or Aggr e gat e is for objects that use external iterators � I t e r at or is for internal traversal or external iterators Traversable Iterator IteratorAggregate + rewind () : void + valid () : boolean + current () : mixed + getIterator () : Iterator + key () : mixed + next () : void Marcus Börger Objects for the Masses 94
Implementing Iterators Traversable Iterator IteratorAggregate + rewind () : void + valid () : boolean + getIterator () : Iterator + current () : mixed + key () : mixed + next () : void IteratorImpl AggregateImpl + <<Implement>> rewind () : void + <<Implement>> valid () : boolean + <<Implement>> getIterator () : Iterator + <<Implement>> current () : mixed + <<Implement>> key () : mixed + <<Implement>> next () : void Marcus Börger Objects for the Masses 95
How Iterators work � Iterators can be used manually � Iterators can be used implicitly with foreach <? php $o = ne w Ar r a yI t e r a t or ( ar r a y( 1, 2, 3) ) ; $o- >r e wi nd( ) ; whi l e ( $o- >va l i d( ) ) { $ke y = $o- >ke y( ) ; $va l = $o- >c ur r e nt ( ) ; / / s om e c ode $o- >ne xt ( ) ; } ? > <? php $o = ne w Ar r a yI t e r a t or ( ar r a y( 1, 2, 3) ) ; f or e a c h( $o a s $ke y => $va l ) { / / s om e c ode } ? > Marcus Börger Objects for the Masses 96
How Iterators work � Internal I terators � User Iterators < ?php interface Iterator { function rewind(); function valid(); function current(); function key(); function next(); } ?> < ?php $it = get_resource(); for ($it-> rewind(); $it-> valid(); $it-> next()) { $value = $it-> current(); $key = $it-> key(); } ?> Marcus Börger Objects for the Masses 97
How Iterators work � Internal I terators � User Iterators < ?php interface Iterator { function rewind(); function valid(); < ?php function current(); $it = get_resource(); function key(); foreach($it as $key= > $val) { function next(); / / access data } } ?> ?> Marcus Börger Objects for the Masses 98
How Iterators work � Internal I terators � User Iterators < ?php class FilterIterator implements Iterator { < ?php function __construct(Iterator $input)... interface Iterator { function rewind()... function rewind(); function accept()... function valid(); function valid()... function current(); function current()... function key(); function key()... function next(); function next()... } } ?> ?> < ?php $it = get_resource(); foreach(new Filter($it, $filter_param) as $key= > $val) { / / access filtered data only } ?> Marcus Börger Objects for the Masses 99
Debug Session <? php <? php PHP 5.1 c l a s s Ar r a yI t er a t or { $a = a r r a y( 1, 2, 3) ; pr ot e c t e d $a r ; $o = ne w Ar r a yI t e r a t or ( $a ) ; f unc t i on __c ons t r uc t ( Ar r a y $ar ) { f or e a c h( $o a s $ke y => $va l ) { $t hi s - >a r = $ar ; e c ho " $ke y => $va \ n" ; } } f unc t i on r e wi nd( ) { ? > r e wi nd( $t hi s - >a r ) ; } f uc nt i on va l i d( ) { 0 => 1 r e t ur n ! i s _nul l ( ke y( $t hi s - >a r ) ) ; 1 => 2 } 2 => 3 f unc t i on ke y( ) { r e t ur n ke y( $t hi s - >a r ) ; } f uc nt i on c ur r ent ( ) { r e t ur n c ur r e nt ( $t hi s - >a r ) ; } f unc t i on ne xt ( ) { ne xt ( $t hi s - >a r ) ; } } ? > Marcus Börger Objects for the Masses 100
Recommend
More recommend