Objects for the Masses Marcus Brger PHP Quebec 0 9 : http:/ / - - PowerPoint PPT Presentation

objects for the masses
SMART_READER_LITE
LIVE PREVIEW

Objects for the Masses Marcus Brger PHP Quebec 0 9 : http:/ / - - PowerPoint PPT Presentation

Objects for the Masses Marcus Brger PHP Quebec 0 9 : http:/ / talks.som abo.de/ 2 0 0 9 0 3 .pdf | .pps Overview 3 What is OOP? 25 PHP & OOP 29 PHP OOP In Detail 48 Class Design 50 Dynamic Class Loading 55 Exceptions 77 Reflection


slide-1
SLIDE 1

Objects for the Masses

Marcus Börger

PHP Quebec 0 9 : http:/ / talks.som abo.de/ 2 0 0 9 0 3 .pdf | .pps

slide-2
SLIDE 2

Marcus Börger Objects for the Masses 2

Overview

3 What is OOP? 25 PHP & OOP 29 PHP OOP In Detail 48 Class Design 50 Dynamic Class Loading 55 Exceptions 77 Reflection 80 Built-in I nterfaces 108 Design Patterns

slide-3
SLIDE 3

Marcus Börger Objects for the Masses 3

What is OOP

c l a s s Us e l e s s e xt e nds Nons e ns e { a bs t r a c t f unc t i on bl a Bl a ( ) ; }

?

slide-4
SLIDE 4

Marcus Börger Objects for the Masses 4

What does OOP aim to achieve?

  • Allow compartmentalized refactoring of code.
  • Promote code re-use.
  • Promote extensibility, flexibility and adaptability.
  • Better for team development.
  • Many patterns are designed for OOP.
  • Some patterns lead to much more efficient code.
  • Do you need to use OOP to achieve these goals?
  • Of course not.
  • It’s designed to make those things easier though.
slide-5
SLIDE 5

Marcus Börger Objects for the Masses 5

What are the features of OOP?

  • Encapsulation
  • Inheritance
  • Polymorphism
slide-6
SLIDE 6

Marcus Börger Objects for the Masses 6

Encapsulation

  • Encapsulation is about grouping of functionality

(operations) and related data (attributes) together into a coherent data structure (classes).

slide-7
SLIDE 7

Marcus Börger Objects for the Masses 7

Encapsulation

  • Encapsulation is about grouping of functionality

(operations) and related data (attributes) together into a coherent data structure (classes).

  • Classes represent complex data types and the
  • perations that act on them. An object is a

particular instance of a class.

slide-8
SLIDE 8

Marcus Börger Objects for the Masses 8

Encapsulation

  • Encapsulation is about grouping of functionality

(operations) and related data (attributes) together into a coherent data structure (classes).

  • Classes represent complex data types and the
  • perations that act on them. An object is a

particular instance of a class.

  • The basic idea is to re-code real life.

For instance, if you press a key on your laptop keyboard you do not know what is happening in detail. For you it is the same as if you press the keyboard of an ATM. We say the interface is the sam e. If another person has the same laptop the internal details would be exactly the same.

slide-9
SLIDE 9

Marcus Börger Objects for the Masses 9

Encapsulation

  • Encapsulation is about grouping of functionality

(operations) and related data (attributes) together into a coherent data structure (classes).

  • Classes represent complex data types and the
  • perations that act on them. An object is a

particular instance of a class.

  • The basic idea is to re-code real life.

For instance, if you publish a text that is not really different from publishing a picture. Both are content types and you might want to encapsulate the details on how to do the actual publishing in a class. And once you have that you can easily have content that consists of both pictures and text and yet use the same operations for publishing. Then later you might publish tables using the same interface.

slide-10
SLIDE 10

Marcus Börger Objects for the Masses 10

Encapsulation: Are Objects Just Dictionaries?

  • In PHP 4 objects were little more than arrays.
  • In PHP 5 you get much more control by visibility,

interfaces, type hints, interceptors and more.

  • Another difference is coherency. Classes can be

told to automatically execute specific code on

  • bject creation and destruction.

c l a s s Si m pl e { f unc t i on __c ons t r uc t ( ) { / *. . . */ } f unc t i on __de s t r uc t ( ) { / *. . . */ } }

slide-11
SLIDE 11

Marcus Börger Objects for the Masses 11

  • Another difference between objects and arrays is

that objects permit strict visibility semantics. Data hiding eases refactoring by controlling what other parties can access in your code.

  • public

anyone can access it

  • protected
  • nly descendants can access it
  • private
  • nly you can access it
  • final

no one can re-declare it

  • abstract

someone else will implement this Why have these in PHP? Because som etimes self-discipline isn’t enough.

Data Hiding

slide-12
SLIDE 12

Marcus Börger Objects for the Masses 12

Inheritance

  • Inheritance allows a class to specialize (or extend)

another class and inherit all its methods, properties and behaviors.

  • This promotes
  • Extensibility
  • Reusability
  • Code Consolidation
  • Abstraction
  • Responsibility
slide-13
SLIDE 13

Marcus Börger Objects for the Masses 13

The Problem of Code Duplication

  • Code duplication contradicts maintainability.

You often end up with code that looks like this: f unc t i on f oo_t o_xm l ( $f oo) { / / ge ne r i c s t uf f / / f oo- s pe c i f i c s t uf f } f unc t i on ba r _t o_xm l ( $ba r ) { / / ge ne r i c s t uf f / / ba r s pe c i f i c s t uf f }

slide-14
SLIDE 14

Marcus Börger Objects for the Masses 14

The Problem of Code Duplication

  • You could clean that up as follows

f unc t i on ba s e _t o_xm l ( $da t a ) { / *. . . */ } f unc t i on f oo_t o_xm l ( $f oo) { ba s e _t o_xm l ( $f oo) ; / / f oo s pe c i f i c s t uf f } f unc t i on ba r _t o_xm l ( $ba r ) { ba s e _t o_xm l ( $ba r ) ; / / ba r s pe c i f i c s t uf f }

  • But it’s hard to keep base_to_xml() working for

the disparate foo and bar types.

slide-15
SLIDE 15

Marcus Börger Objects for the Masses 15

The Problem of Code Duplication

  • In an OOP style you would create classes for the

Foo and Bar classes that extend from a base class that handles common functionality.

  • Sharing a base class promotes sameness.

c l a s s Ba r e xt e nds Ba s e { publ i c f unc t i on t oXM L( ) { pa r e nt : : t oXM L( ) ; / / ba r s pe c i f i c s t uf f } } c l a s s Ba s e { publ i c f unc t i on t oXM L( ) { / *. . . */ } } c l a s s Foo e xt e nds Ba s e { publ i c f unc t i on t oXM L( ) { pa r e nt : : t oXM L( ) ; / / f oo s pe c i f i c s t uf f } }

slide-16
SLIDE 16

Marcus Börger Objects for the Masses 16

Polymorphism?

  • Suppose a calendar that is a collection of entries.

Procedurally dislpaying all the entries might look like: f or e a c h( $e nt r i e s a s $e nt r y) { s wi t c h( $e nt r y[ ’ t ype ’ ] ) { c a s e ' pr of e s s i ona l ' : di s pl a y_pr of e s s i ona l _e nt r y( $e nt r y) ; br e a k; c a s e ' pe r s ona l ' : di s pl a y_pe r s ona l _e nt r y( $e nt r y) ; br e a k; } }

slide-17
SLIDE 17

Marcus Börger Objects for the Masses 17

  • In the OOP paradigm this would look like:

f or e a c h( $e nt r i e s a s $e nt r y) { $e nt r y- >di s pl a y( ) ; }

  • The key point is we don't have to modify this loop

to add new types. When we add a new type, that type gets a display() method so that it knows how to display itself, and we’re done.

  • Also this is much faster because we do not have to

check the type for every element.

Simplicity through Polymorphism

slide-18
SLIDE 18

Marcus Börger Objects for the Masses 18

  • Actually in PHP you might want this:

f or e a c h( $e nt r i e s a s $e nt r y) { e c ho $e nt r y; }

  • A class can have a __t oSt r i ng( ) method which

defines how its objects are converted into a textual representation.

  • PHP 5.2 supports this in all string contexts.

Simplicity through Magic?

slide-19
SLIDE 19

Marcus Börger Objects for the Masses 19

Polymorphism the other way round

  • Unlike other languages PHP does not and will not
  • ffer polymorphism for method calling. Thus the

following will never be available in PHP < ?php class Test { function toXML(Personal $obj) / / … function toXML(Professional $obj) / / … } ?>

  • To work around this
  • Use the other way round (call other methods from a

single toXML() function in a polymorphic way)

  • Use switch/ case (though this is not the OO way)
slide-20
SLIDE 20

Marcus Börger Objects for the Masses 20

Another example

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 ) { / *. . . */ } 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 s nor e ( ) { / *. . . */ } publ i c f unc t i on wa ke up( ) { / *. . . */ } }

slide-21
SLIDE 21

Marcus Börger Objects for the Masses 21

Some Inheritance

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 ) { / *. . . */ } 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 s nor e ( ) { / *. . . */ } publ i c f unc t i on wa ke up( ) { / *. . . */ } } c l a s s W

  • m

e n e xt e nds Hum a ns { publ i c f unc t i on gi ve Bi r t h( ) { / *. . . */ } }

slide-22
SLIDE 22

Marcus Börger Objects for the Masses 22

Inheritance+ Polymorphism

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 ) { / *. . . */ } 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

  • m

e n e xt e nds Hum a ns { 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 s nor e ( ) { / *. . . */ } }

slide-23
SLIDE 23

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

  • 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 ' 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 ( ) { / *. . . */ } }

slide-24
SLIDE 24

Marcus Börger Objects for the Masses 24

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

  • 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 ' 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 ( ) { / *. . . */ } }

slide-25
SLIDE 25

Marcus Börger Objects for the Masses 25

PHP & OOP

slide-26
SLIDE 26

Marcus Börger Objects for the Masses 26

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
slide-27
SLIDE 27

Marcus Börger Objects for the Masses 27

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?)
slide-28
SLIDE 28

Marcus Börger Objects for the Masses 28

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
slide-29
SLIDE 29

Marcus Börger Objects for the Masses 29

PHP 5 OOP I n Detail

slide-30
SLIDE 30

Marcus Börger Objects for the Masses 30

  • 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 = ne w Obj e c t ( ) ; $r e f = $obj ; $dup = c l one $obj ;

Objects referenced by identifiers

Class Object $obj $ref $dup Instance 1 Instance 2

slide-31
SLIDE 31

Marcus Börger Objects for the Masses 31

  • 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 ) ;

Constructors and Destructors

slide-32
SLIDE 32

Marcus Börger Objects for the Masses 32

  • 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 ) ;

Constructors and Destructors

slide-33
SLIDE 33

Marcus Börger Objects for the Masses 33

  • 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 { va r $pr op = " He l l o\ n" ; } $obj 1 = ne w Obj e c t ; $obj 1- >pr op = " He l l o W

  • r l d\ n" ;

$obj 2 = ne w Obj e c t ; e c ho $obj 2- >pr op; / / He l l o

Default property values

Class Object $prop/default $obj2 Instance 2 $prop $obj1 Instance 1 $prop

slide-34
SLIDE 34

Marcus Börger Objects for the Masses 34

  • Static methods and properties
  • Bound to the class not to the object
  • Only exists once per class rather than per instance
  • Can be initialized

c l a s s Obj e c t { va r $pr op; 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 ; } } Obj e c t : : t e s t ( ) ; $obj 1 = ne w Obj e c t ; $obj 2 = ne w Obj e c t ;

Static members

Class Object $stat $obj2 Instance 2 $prop $obj1 Instance 1 $prop

slide-35
SLIDE 35

Marcus Börger Objects for the Masses 35

Pseudo constants

  • __CLASS__

shows the current class name

  • __M

ETH O D__ shows class and method or function

  • s e l f

references the class itself

  • 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" ; } }

slide-36
SLIDE 36

Marcus Börger Objects for the Masses 36

  • 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 ; pr ot e c t e d $b; pr i vat e $c ; } c l a s s De r i ve d e xt e nds Ba s e { publ i c $a ; publ i c $b; pr i vat e $c ; }

Visibility

Base $a $b $c Derived $a $b $c Base::$c

slide-37
SLIDE 37

Marcus Börger Objects for the Masses 37

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 ( ) { } }

slide-38
SLIDE 38

Marcus Börger Objects for the Masses 38

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" ;

slide-39
SLIDE 39

Marcus Börger Objects for the Masses 39

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

  • r 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 ( ) ;

slide-40
SLIDE 40

Marcus Börger Objects for the Masses 40

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" ; } }

slide-41
SLIDE 41

Marcus Börger Objects for the Masses 41

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 { }

slide-42
SLIDE 42

Marcus Börger Objects for the Masses 42

  • 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( ) { f or e a c h( $t hi s - >l i ne s a s $l i ne) $l i ne - >dr a w( ) ; } } c l a s s Re c t a ngl e e xt e nds Pol ygon { } 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( ) ; } }

Different Object same behavior

Polygon Line Ellipse Circle $lines Rectangle

slide-43
SLIDE 43

Marcus Börger Objects for the Masses 43

  • 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( ) ; } 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( ) { f or e a c h( $t hi s - >l i ne s a s $l i ne) $l i ne - >dr a w( ) ; } } c l a s s Re c t a ngl e e xt e nds Pol ygon { } 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( ) ; } }

Interfaces

Drawable Polygon Line Ellipse Circle $lines Rectangle

slide-44
SLIDE 44

Marcus Börger Objects for the Masses 44

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
slide-45
SLIDE 45

Marcus Börger Objects for the Masses 45

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

slide-46
SLIDE 46

Marcus Börger Objects for the Masses 46

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" ; } }

slide-47
SLIDE 47

Marcus Börger Objects for the Masses 47

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 } } }

slide-48
SLIDE 48

Marcus Börger Objects for the Masses 48

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

Vehicle Truck Car Bus Diesel Gasoline Engine Bicycle Plane Tires Turbine Tank

slide-49
SLIDE 49

Marcus Börger Objects for the Masses 49

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
slide-50
SLIDE 50

Marcus Börger Objects for the Masses 50

Dynam ic Class Loading

slide-51
SLIDE 51

Marcus Börger Objects for the Masses 51

Dynamic class loading

  • __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

  • __a ut ol oa d( ) is good when you're alone
slide-52
SLIDE 52

Marcus Börger Objects for the Masses 52

__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 ' ) ; } ? >

slide-53
SLIDE 53

Marcus Börger Objects for the Masses 53

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' ) ; } ? >

slide-54
SLIDE 54

Marcus Börger Objects for the Masses 54

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

slide-55
SLIDE 55

Marcus Börger Objects for the Masses 55

Exceptions

slide-56
SLIDE 56

Marcus Börger Objects for the Masses 56

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 } ? >

slide-57
SLIDE 57

Marcus Börger Objects for the Masses 57

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 }

slide-58
SLIDE 58

Marcus Börger Objects for the Masses 58

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 }

slide-59
SLIDE 59

Marcus Börger Objects for the Masses 59

Practical use of exceptions

  • Constructor failure
  • Converting errors/ warnings to exceptions
  • Simplify error handling
  • Provide additional error information by tagging
slide-60
SLIDE 60

Marcus Börger Objects for the Masses 60

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) ; } ? >

slide-61
SLIDE 61

Marcus Börger Objects for the Masses 61

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" ; } ? >

slide-62
SLIDE 62

Marcus Börger Objects for the Masses 62

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; } } } ? >

slide-63
SLIDE 63

Marcus Börger Objects for the Masses 63

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 ' ) ; ? >

slide-64
SLIDE 64

Marcus Börger Objects for the Masses 64

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 >

slide-65
SLIDE 65

Marcus Börger Objects for the Masses 65

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 >

slide-66
SLIDE 66

Marcus Börger Objects for the Masses 66

SPL Exceptions

  • SPL provides a standard set of exceptions
  • Class Exception must be the root of all exceptions
slide-67
SLIDE 67

Marcus Börger Objects for the Masses 67

General distinguishing

  • Logi c Exc e pt i on

Ł Anything that could have been detected at compile time, during application design

  • r 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

slide-68
SLIDE 68

Marcus Börger Objects for the Masses 68

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
slide-69
SLIDE 69

Marcus Börger Objects for the Masses 69

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
slide-70
SLIDE 70

Marcus Börger Objects for the Masses 70

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 ) { $t hi s - >i t = $i t ; } 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 ) ; } }

Compile-Time: Error in design

slide-71
SLIDE 71

Marcus Börger Objects for the Masses 71

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 { f unc t i on __c ons t r uc t ( I t e r a t or $i t ) { $t hi s - >i t = $i t ; } 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 ) ; } } I nt e r f a c e I t e r a t or { f unc t i on r e wi nd( ) ; f unc t i on va l i d( ) ; f unc t i on c ur r e nt ( ) ; f unc t i on ke y( ) ; f unc t i on ne xt ( ) ; }

slide-72
SLIDE 72

Marcus Börger Objects for the Masses 72

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 { f unc t i on __c ons t r uc t ( I t e r a t or $i t ) { $t hi s - >i t = $i t ; } 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 ) ; } 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 ( ) ; } } I nt e r f a c e I t e r a t or { f unc t i on r e wi nd( ) ; f unc t i on va l i d( ) ; f unc t i on c ur r e nt ( ) ; f unc t i on ke y( ) ; f unc t i on ne xt ( ) ; }

slide-73
SLIDE 73

Marcus Börger Objects for the Masses 73

Expecting formatted data

  • Opening a file for reading

$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( ) ; Run-Time: File might not be accessible or exist

slide-74
SLIDE 74

Marcus Börger Objects for the Masses 74

Run-Time: data is different for every execution

Expecting formatted data

  • Reading a formatted file line by line

$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( ) ; } $da t a [ ] = $l ; }

  • ! 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 Run-Time: File might not be accessible or exist

slide-75
SLIDE 75

Marcus Börger Objects for the Masses 75

Expecting formatted data

  • Cehcking data after pre-processing

$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( ) ; } $da t a [ ] = $l ; } / / 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( ) ; Run-Time: data is different for every execution Run-Time: Filemight not be accessible or exist

slide-76
SLIDE 76

Marcus Börger Objects for the Masses 76

Expecting formatted data

  • Processing pre-checked data

$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( ) ; } $da t a [ ] = $l ; } 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

  • r e pr e c e s s i ng c ode

f or e a c h( $da t a a s & $v) { i f ( c ount ( $v) == 2) { t hr ow ne w Dom a i nExc e pt i on( ) ; } $v = $v[ 0] * $v[ 1] ; } Compile-Time: exception signals failed precondition Run-Time: data is different for every execution Run-Time: File might not be accessible or exist

slide-77
SLIDE 77

Marcus Börger Objects for the Masses 77

Reflection

slide-78
SLIDE 78

Marcus Börger Objects for the Masses 78

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' ) ;

slide-79
SLIDE 79

Marcus Börger Objects for the Masses 79

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) ) ;

slide-80
SLIDE 80

Marcus Börger Objects for the Masses 80

Built-in I nterfaces

slide-81
SLIDE 81

Marcus Börger Objects for the Masses 81

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

slide-82
SLIDE 82

Marcus Börger Objects for the Masses 82

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 ) ; }

slide-83
SLIDE 83

Marcus Börger Objects for the Masses 83

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 &

  • f 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 ) { / * . . . */ } }

slide-84
SLIDE 84

Marcus Börger Objects for the Masses 84

ArrayAccess Example

  • We want to create variables which can be shared

between processes.

  • We will set up interception so that access attempts
  • n the variable are actually performed through a

DBM file.

slide-85
SLIDE 85

Marcus Börger Objects for the Masses 85

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) ; } } ? >

slide-86
SLIDE 86

Marcus Börger Objects for the Masses 86

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 ' ] ) ; ? >

slide-87
SLIDE 87

Marcus Börger Objects for the Masses 87

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

  • r l d\ n" ;

} f or e a c h( ne w Obj e c t a s $pr op) { e c ho $pr op; } ? >

slide-88
SLIDE 88

Marcus Börger Objects for the Masses 88

What are Iterators

  • Iterators are a concept to iterate anything that

contains other things.

  • Iterators allow to encapsulate algorithms
slide-89
SLIDE 89

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
slide-90
SLIDE 90

Marcus Börger Objects for the Masses 90

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 , . . .

slide-91
SLIDE 91

Marcus Börger Objects for the Masses 91

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 ()

slide-92
SLIDE 92

Marcus Börger Objects for the Masses 92

The big difference

  • Arrays
  • require memory for all elements
  • allow to access any element directly
  • I terators
  • nly know one element at a time
  • nly 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
slide-93
SLIDE 93

Marcus Börger Objects for the Masses 93

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
slide-94
SLIDE 94

Marcus Börger Objects for the Masses 94

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

IteratorAggregate + getIterator () : Iterator Traversable Iterator + + + + + rewind () valid () current () key () next () : void : boolean : mixed : mixed : void

slide-95
SLIDE 95

Marcus Börger Objects for the Masses 95

Implementing Iterators

Traversable IteratorAggregate + getIterator () : Iterator Iterator + + + + + rewind () valid () current () key () next () : void : boolean : mixed : mixed : void AggregateImpl + <<Implement>> getIterator () : Iterator IteratorImpl + + + + + <<Implement>> <<Implement>> <<Implement>> <<Implement>> <<Implement>> rewind () valid () current () key () next () : void : boolean : mixed : mixed : void

slide-96
SLIDE 96

Marcus Börger Objects for the Masses 96

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 } ? >

slide-97
SLIDE 97

Marcus Börger Objects for the Masses 97

< ?php $it = get_resource(); for ($it-> rewind(); $it-> valid(); $it-> next()) { $value = $it-> current(); $key = $it-> key(); } ?>

How Iterators work

  • Internal I terators
  • User Iterators

< ?php interface Iterator { function rewind(); function valid(); function current(); function key(); function next(); } ?>

slide-98
SLIDE 98

Marcus Börger Objects for the Masses 98

How Iterators work

  • Internal I terators
  • User Iterators

< ?php $it = get_resource(); foreach($it as $key= > $val) { / / access data } ?> < ?php interface Iterator { function rewind(); function valid(); function current(); function key(); function next(); } ?>

slide-99
SLIDE 99

Marcus Börger Objects for the Masses 99

< ?php $it = get_resource(); foreach(new Filter($it, $filter_param) as $key= > $val) { / / access filtered data only } ?> < ?php class FilterIterator implements Iterator { function __construct(Iterator $input)... function rewind()... function accept()... function valid()... function current()... function key()... function next()... } ?>

How Iterators work

  • Internal I terators
  • User Iterators

< ?php interface Iterator { function rewind(); function valid(); function current(); function key(); function next(); } ?>

slide-100
SLIDE 100

Marcus Börger Objects for the Masses 100

Debug Session

<? php c l a s s Ar r a yI t er a t or { pr ot e c t e d $a r ; f unc t i on __c ons t r uc t ( Ar r a y $ar ) { $t hi s - >a r = $ar ; } 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( ) { r e t ur n ! i s _nul l ( ke y( $t hi s - >a r ) ) ; } 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 ) ; } } ? > <? php $a = a r r a y( 1, 2, 3) ; $o = ne w Ar r a yI t e r a t or ( $a ) ; f or e a c h( $o a s $ke y => $va l ) { e c ho " $ke y => $va \ n" ; } ? > 0 => 1 1 => 2 2 => 3

PHP 5.1

slide-101
SLIDE 101

Marcus Börger Objects for the Masses 101

  • Why not just use arrays:

f or e a c h( $s om e _a r r a y a s $i t e m ) {/ *. . . */ }

  • Aren't we making life more difficult than need be?
  • No! For simple aggregations the above works fine

(though it’s slow), but not everything is an array. What about:

  • Buffered result sets
  • Lazy Initialization
  • Directories
  • Anything not already an array

Aren’t Iterators Pointless in PHP?

slide-102
SLIDE 102

Marcus Börger Objects for the Masses 102

Iterators by example

  • Using Iterators you can efficiently grab all groups

from INI files

  • The building blocks:
  • A class that handles INI files
  • An abstract filter Iterator
  • A filter that filters group names from the INI file input
  • An Iterator to read all entries in the INI file
  • Another filter that allow to search for specific groups
slide-103
SLIDE 103

Marcus Börger Objects for the Masses 103

INI file abstraction

/ / Re m e m be r Dba Ac c e s s f r om pa ge 86? / / 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 . . . c l a s s Dba Re a de r e xt e nds Dba Ac c e s s i m pl e m e nt s I t e r a t or { pr i va t e $ke y = f a l s e , $va l = f a l s e ; pr i va t e f unc t i on f e t c h_da t a ( $ke y) { i f ( ( $t hi s - >ke y = $ke y) ! == f a l s e ) $t hi s - >va l = dba _f e t c h( $t hi s - >ke y, $t hi s - >db) ; } f unc t i on r e wi nd( ) { $t hi s - >f e t c h_da t a ( dba _f i r s t ke y( $t hi s - >db) ) ; } f unc t i on ne xt ( ) { $t hi s - >f e t c h_da t a ( dba _ne xt ke y( $t hi s - >db) ) ; } f unc t i on c ur r e nt ( ) { r e t ur n $t hi s - >va l ; } f unc t i on va l i d( ) { r e t ur n $t hi s - >ke y ! == f a l s e ; } f unc t i on ke y( ) { r e t ur n $t hi s - >ke y; } } c l a s s I ni Fi l e e xt e nds Dba Re a de r { f unc t i on __c ons t r uc t ( $f i l e na m e ) { pa r e nt : : __c ons t r uc t ( $f i l e na m e , ' i ni f i l e ' ) ; } }

slide-104
SLIDE 104

Marcus Börger Objects for the Masses 104

Filtering Iterator keys

  • FilterIteraor is an abstract class
  • Abstract accept() is called from rewind() and next()
  • When accept() returns false next() will be called automatically

<? php c l a s s Ke yFi l t e r e xt e nds Fi l t e r I t e r a t or { pr i va t e $r x; f unc t i on __c ons t r uc t ( I t e r a t or $i t , $r e ge x) { pa r e nt : : __c ons t r uc t ( $i t ) ; $t hi s - >r x = $r e ge x; } f unc t i on a c c e pt ( ) { r e t ur n e r e g( $t hi s - >r x, $t hi s - >ge t I nne r I t e r a t or ( ) - >ke y( ) ) ; } f unc t i on ge t Re ge x( ) { r e t ur n $t hi s - >r x; } pr ot e c t e d f unc t i on __c l one ( $t ha t ) { / / di s a l l ow c l one } } ? >

slide-105
SLIDE 105

Marcus Börger Objects for the Masses 105

Getting only INI groups

<? php i f ( ! c l a s s _e xi s t s ( ' Ke yFi l t e r ' , f a l s e ) ) { r e qui r e _onc e ( ' ke yf i l t e r . i nc ' ) ; } c l a s s I ni Gr oups e xt e nds Ke yFi l t e r { f unc t i on __c ons t r uc t ( $f i l e na m e ) { pa r e nt : : __c ons t r uc t ( ne w I ni Fi l e ( $f i l e na m e ) , ' ^\ [ . *\ ] $' ) ; } f unc t i on c ur r e nt ( ) { r e t ur n s ubs t r ( pa r e nt : : ke y( ) , 1, - 1) ; } f unc t i on ke y( ) { r e t ur n s ubs t r ( pa r e nt : : ke y( ) , 1, - 1) ; } } ? >

slide-106
SLIDE 106

Marcus Börger Objects for the Masses 106

Putting it to work

<? php i f ( ! c l a s s _e xi s t s ( ' Ke yFi l t e r ' , f a l s e ) ) { r e qui r e _onc e ( ' ke yf i l t e r . i nc ' ) ; } i f ( ! c l a s s _e xi s t s ( ' I ni Gr oups ' , f a l s e ) ) { r e qui r e _onc e ( ' i ni gr oups . i nc ' ) ; } $i t = ne w I ni Gr oups ( $a r gv[ 1] ) ; i f ( $a r gc > 2) { $i t = ne w Ke yFi l t e r ( $i t , $a r gv[ 2] ) ; } f or e a c h( $i t a s $gr oup) { e c ho $gr oup . " \ n" ; } ? >

Avoid calling __a ut ol oa d( )

slide-107
SLIDE 107

Marcus Börger Objects for the Masses 107

Conclusion so far

  • Iterators require a new way of programming
  • Iterators allow to implement algorithms

abstracted from data

  • Iterators promote code reuse
  • Some things are already in SPL
  • Filtering
  • Handling recursion
  • Limiting
  • The above are all “Decorator” patterns
slide-108
SLIDE 108

Marcus Börger Objects for the Masses 108

Design Patterns

slide-109
SLIDE 109

Marcus Börger Objects for the Masses 109

Let’s Talk About Patterns

  • Patterns catalog solutions to problem categories
  • They consist of
  • A name
  • A description of their problem
  • A description of the solution
  • An assessm ent of the pros and cons of the pattern
slide-110
SLIDE 110

Marcus Börger Objects for the Masses 110

  • Not so much.

Patterns sources outside OOP include:

  • Architecture (the originator of the paradigm)
  • User Interface Design (wizards, cookie crumbs,

tabs)

  • Cooking (braising, pickling)

What do patterns have to do with OOP?

slide-111
SLIDE 111

Marcus Börger Objects for the Masses 111

Patterns We’ve Seen So Far

  • Singleton Pattern
  • Proxy Pattern
  • Iterator Pattern
  • Decorator Pattern
  • Factory Pattern
slide-112
SLIDE 112

Marcus Börger Objects for the Masses 112

  • Problem : You have collections of items that you
  • perate on frequently with lots of repeated code.

Remember our calendars:

f or e a c h( $e nt r i e s a s $e nt r y) { e c ho $e nt r y; }

  • Solution: Create a container that implements the

same interface, and perfoms the iteration for you.

Aggregator Pattern

slide-113
SLIDE 113

Marcus Börger Objects for the Masses 113

c l a s s Ent r yAggr e ga t e e xt e nds Ent r y { pr ot e c t e d $e nt r i e s ; . . . publ i c f unc t i on di s pl a y( ) { f or e a c h( $t hi s - >e nt r i e s a s $e nt r y) { $e nt r y- >di s pl a y( ) ; } publ i c f unc t i on a dd( Ent r y $e ) { a r r a y_pus h( $t hi s - >e nt r i e s , $e ) ; } }

  • By extending Entry, the aggregate can actually

stand in any place that entry did, and can itself contain other aggregated collections.

Aggregator Pattern

slide-114
SLIDE 114

Marcus Börger Objects for the Masses 114

  • Problem : You need to provide access to an
  • bject, but it has an interface you don’t know at

compile time.

  • Solution: Use accessor/ method overloading to

dynamically dispatch methods to the object.

  • Discussion: This is very typical of RPC-type

facilities like SOAP where you can interface with the service by reading in a definitions file of some sort at runtime.

Proxy Pattern

slide-115
SLIDE 115

Marcus Börger Objects for the Masses 115

<? php c l a s s SOAP_Cl i e nt { publ i c $ws dl ; publ i c f unc t i on __c ons t r uc t ( $e ndpoi nt ) { $t hi s - >ws dl = W SDLM a na ge r : : ge t ( $e ndpoi nt ) ; } publ i c f unc t i on __c a l l ( $m e t hod, $a r gs ) { $por t = $t hi s - >ws dl - >ge t Por t For Ope r a t i on( $m e t hod) ; $t hi s - >e ndpoi nt =$t hi s - >ws dl - >ge t Por t Endpoi nt ( $por t ) ; $r e que s t = SOAP_Enve l ope : : r e que s t ( $t hi s - >ws dl ) ; $r e que s t - >a ddM e t hod( $m e t hod, $a r gs ) ; $da t a = $r e que s t - >s a ve XM L( ) ; r e t ur n SOAP_Enve l ope : : pa r s e ( $t hi s - >e ndpoi nt , $da t a ) ; } } ? >

Proxy Pattern in PEAR SOAP

slide-116
SLIDE 116

Marcus Börger Objects for the Masses 116

  • Problem : You have a class that does – more or

less – what you need. But you need a few tweaks.

  • Solution: Write a class that works like a proxy,

but all at compile time. So in the end, to the user, your new class looks exactly like old one. And mostly does the same. That is, because most calls are just passed through. But in some “stubs” you do some work.

  • Discussion: We have seen a few examples with
  • Iterators. We could thing here of a two column

view with left column showing odd and right showing even entries. Easy for a Decorator.

Decorator Pattern

slide-117
SLIDE 117

Marcus Börger Objects for the Masses 117

  • Problem : You want an object to automatically

notify dependents when it is updated.

  • Solution: Allow 'observer' to register themselves

with the observable object.

  • Discussion: An object may not apriori know who

might be interested in it. The Observer pattern allows objects to register their interest and supply a notification method.

Observer Pattern

slide-118
SLIDE 118

Marcus Börger Objects for the Masses 118

Object handling side notes

  • You cannot access the object identifier/ handle

$obs e r ve r s [ ] = $obs e r ve r ;

  • YOU need to prevent double insertion/ execution

f or e a c h( $obs e r ve r s a s $o) { i f ( $o === $obs e r ve r ) r e t ur n; } $obs e r ve r s [ ] = $obs e r ve r ;

  • No easy way to delete an object from an array

f or e a c h( $obs e r ve r s a s $k => $o) { i f ( $o === $obs e r ve r ) { uns e t ( $obs e r ve r [ $k] ) ; br e a k; } }

slide-119
SLIDE 119

Marcus Börger Objects for the Masses 119

Object Storage

c l a s s Obj e c t St or a ge { pr ot e c t e d $s t or a ge = a r r a y( ) ; f unc t i on a t t a c h( $obj ) { f or e a c h( $t hi s - >s t or a ge a s $o) { i f ( $o === $obj ) r e t ur n; } $t hi s - >s t or a ge [ ] = $obj ; } f unc t i on de t a t c h( $obj ) { f or e a c h( $t hi s - >s t or a ge a s $k => $o) { i f ( $o === $obj ) { uns e t ( $t hi s - >s t or a ge [ $k] ) ; r e t ur n; } } } }

slide-120
SLIDE 120

Marcus Börger Objects for the Masses 120

Object Storage in 5.2

c l a s s Obj e c t St or a ge { pr ot e c t e d $s t or a ge = a r r a y( ) ; f unc t i on a t t a c h( $obj ) { $t hi s - >s t or a ge [ s pl _obj e c t _ha s h( $obj ) ] = $obj ; } f unc t i on de t a t c h( $obj ) { uns e t ( $t hi s - >s t or a ge [ s pl _obj e c t _ha s h( $obj ) ] ) ; } }

  • Or simply use Spl O

bj e c t St or age

slide-121
SLIDE 121

Marcus Börger Objects for the Masses 121

c l a s s M ySubj e c t i m pl e m e nt s Subj e c t { pr ot e c t e d $obs e r ve r s ; publ i c f unc t i on __c ons t r uc t ( ) { $t hi s - >obs e r ve r = ne w Obj e c t St or a ge ; } publ i c f unc t i on a t t a c h( Obs e r ve r $o) { $t hi s - >obs e r ve r s - >a t t a c h( $o) ; } publ i c f unc t i on de t a c h( Obs e r ve r $o) { $t hi s - >obs e r ve r s - >de t a c h( $o) ; } publ i c f unc t i on not i f y( ) { f or e a c h( $t hi s - >obs e r ve r s a s $o) $o- >upda t e ( $t hi s ) ; } } c l a s s M yObs e r ve r i m pl e m e nt s Obs e r ve r { publ i c f unc t i on upda t e ( Subj e c t $s ) { / / do l oggi ng or s om e ot he r a c t i on } }

  • Concrete Examples: logging facilities: email,

debugging, SOAP message notifications.

Observer Pattern Implementation

slide-122
SLIDE 122

Marcus Börger Objects for the Masses 122

  • Problem : Need to replace a complex stucture

with something easy for testing or error handling? Or when building an offline version of your app?

  • Solution: Extract the protocol between user (your

app) and the structure (e.g. database). Then write this as an Interface and provide multiple implementations with different backends.

  • Discussion: Often “stuff” just grows. When using

an interface we are limiting ourselves. Because a change to the interface has to be applied to all implementations.

Mock Pattern

slide-123
SLIDE 123

Marcus Börger Objects for the Masses 123

Mocks & Dependency Injection

i nt e r f a c e Da t a Ac c e s s e xt e nds Ar r a yAc c e s s { f unc t i on c onne c t ( $c onne c t i on) ; / / 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 ) ; } / / c l a s s Dba Ac c e s s f r om pa ge 86 a ga i n c l a s s Dba Da t a e xt e nds Dba Ac c e s s i m pl e m e nt s Da t a Ac c e s s { f unc t i on __c ons t r uc t ( ) { pa r e nt : : __c ons t r uc t ( ‘ / de v/ nul l ' , ‘ i ni f i l e ' ) ; } f unc t i on c onne c t ( Ar r a y $c onne c t i on) { $c onne c t i on = s pl i t ( ‘ : ' , $c onne c t i on) ; $t hi s - >db = dba _ope n( $c onne c t i on[ 0] ' c d' , $c onne c t i on[ 1] ) ) } } c l a s s a pp { f unc t i on __c ons t r uc t ( Da t a Ac c e s s $db) { $t hi s - >db = $db; $db- >c onne c t ( ‘ / us r / l oc a l / m yf i l e . db4: db4' ) ; } }

slide-124
SLIDE 124

Marcus Börger Objects for the Masses 124

Mocks & Dependency Injection

i nt e r f a c e Da t a Ac c e s s e xt e nds Ar r a yAc c e s s { f unc t i on c onne c t ( $c onne c t i on) ; / / 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 ) ; } / / How a bout s om e t e s t da t a you c a n r e l y on? c l a s s Te s t Da t a e xt e nds Ar r a yObj e c t i m pl e m e nt s Da t a Ac c e s s { f unc t i on c onne c t ( $f i l e na m e ) { $t hi s [ ‘ ke y1’ ] = ‘ va l ue 1’ ; $t hi s [ ‘ ke y2’ ] = ‘ va l ue 2’ ; $t hi s [ ‘ ke y3’ ] = ‘ va l ue 3’ ; $t hi s [ ‘ ke y4’ ] = ‘ va l ue 4’ ; $t hi s [ ‘ ke y5’ ] = ‘ va l ue 5’ ; } } c l a s s a pp { f unc t i on __c ons t r uc t ( Da t a Ac c e s s $db) { $t hi s - >db = $db; $db- >c onne c t ( ‘ / us r / l oc a l / m yf i l e . db4: db4' ) ; } }

slide-125
SLIDE 125

Marcus Börger Objects for the Masses 125

At Last some Hints

  • List of all SPL classes

PHP 5.0.0

php –r ' pr i nt _r ( a r r a y_ke ys ( s pl _c l a s s e s ( ) ) ) ; '

  • Reflection of a built-in class

PHP 5.1.2

php - - r c <Cl as s >

  • Reflection of a function or method

PHP 5.1.2

php - - r f <Func t i on>

  • Reflection of a loaded extension

PHP 5.1.2

php - - r e <Ex t e ns i on>

  • Extension information/ configuration

PHP 5.2.2

php - - r i <Ex t e ns i on>

slide-126
SLIDE 126

Marcus Börger Objects for the Masses 126

Reference

  • Everythining about PHP

http: / / php.net

  • These slides

http: / / talks.somabo.de

  • SPL Documentaion & Examples

http: / / php.net/ ~ helly/ php/ ext/ spl http: / / cvs.php.net/ php-src/ ext/ spl/ examples http: / / cvs.php.net/ php-src/ ext/ spl/ internal

  • George Schlossnagle

Advanced PHP Programming

  • Andi Gutmans, Stig Bakken, Derick Rethans

PHP 5 Power Programming