Introduction to Object-orientedprogramming with PHPMarcus BörgerPHP Quebec conference 2007Marcus Börger Introduction to Object-oriented programming with PHP 2 OverviewWhat is OOP?PHP and OOPExceptionsIteratorsReflectionPatternsMarcus Börger Introduction to Object-oriented programming with PHP 3 What is OOPclass Uselessextends Nonsense{abstractfunction blaBla(); }?Marcus Börger Introduction to Object-oriented programming with PHP 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.Marcus Börger Introduction to Object-oriented programming with PHP 5 What are the features of OOP?EncapsulationInheritancePolymorphismMarcus Börger Introduction to Object-oriented programming with PHP 6 EncapsulationEncapsulation is about grouping of functionality (operations) and related data (attributes) together into a coherent data structure (classes).Marcus Börger Introduction to Object-oriented programming with PHP 7 EncapsulationEncapsulation is about grouping of functionality (operations) and related data (attributes) together into a coherent data structure (classes).Classes represent complex data types and the operations that act on them. An object is a particular instance of a class.Marcus Börger Introduction to Object-oriented programming with PHP 8 EncapsulationEncapsulation is about grouping of functionality (operations) and related data (attributes) together into a coherent data structure (classes).Classes represent complex data types and the operations 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 same. If another person has the same laptop the internal details would be exactly the same.Marcus Börger Introduction to Object-oriented programming with PHP 9 EncapsulationEncapsulation is about grouping of functionality (operations) and related data (attributes) together into a coherent data structure (classes).Classes represent complex data types and the operations 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 differentfrom 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.Marcus Börger Introduction to Object-oriented programming with PHP 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 object creation and destruction.class Simple{function __construct() { /*...*/}function __destruct() { /*...*/}}Marcus Börger Introduction to Object-oriented programming with PHP 11 Data HidingAnother 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.publicanyone can access itprotectedonly descendants can access it privateonly you can access itfinalno one can re-declare itabstractsomeone else will implement thisWhy have these in PHP? Because sometimes self-discipline isn’t enough.Marcus Börger Introduction to Object-oriented programming with PHP 12 InheritanceInheritance allows a class to specialize (or extend) another class and inherit all its methods, properties and behaviors.This promotesExtensibilityReusabilityCode ConsolidationAbstractionResponsibilityMarcus Börger Introduction to Object-oriented programming with PHP 13 The Problem of Code DuplicationCode duplication contradicts maintainability. You often end up with code that looks like this:functionfoo_to_xml($foo) {//generic stuff//foo-specific stuff}function bar_to_xml($bar) {//generic stuff//bar specific stuff}Marcus Börger Introduction to Object-oriented programming with PHP 14 The Problem of Code DuplicationYou could clean that up as followsfunction base_to_xml($data) { /*...*/}function foo_to_xml($foo) {base_to_xml($foo);//foo specific stuff}function bar_to_xml($bar) {base_to_xml($bar);//bar specific stuff }But it’s hard to keep base_to_xml() working for the disparate foo and bar types.Marcus Börger Introduction to Object-oriented programming with PHP 15 The Problem of Code DuplicationIn 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.class Barextends Base{public function toXML(){parent::toXML();//bar specific stuff}}class Base{public function toXML(){/*...*/}}class Fooextends Base{public function toXML(){parent::toXML();//foospecific stuff}}Marcus Börger Introduction to Object-oriented programming with PHP 16 Polymorphism?Suppose a calendar that is a collection of entries.Procedurally dislpaying all the entries might look like: foreach($entriesas $entry) {switch($entry[’type’]) {case 'professional':display_professional_entry($entry);break;case 'personal':display_personal_entry($entry); break;}}Marcus Börger Introduction to Object-oriented programming with PHP 17 Simplicity through PolymorphismIn the OOP paradigm this would look like:foreach($entriesas $entry) {$entry->display();}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 tocheck the type for every element.Marcus Börger Introduction to Object-oriented programming with PHP 18 Simplicity through Magic?Actually in PHP you might want this:foreach($entriesas $entry) {echo $entry;}A class can have a __toString()method which defines how its objects are converted into a textual representation.PHP 5.2 supports this in all string contexts.Marcus Börger Introduction to Object-oriented programming with PHP 19 Polymorphism the other way roundUnlike other languages PHP does not and will not offer polymorphism for method calling. Thus the following will never be available in PHPTo work around thisUse 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)Marcus Börger Introduction to Object-oriented programming with PHP 20 Another exampleclass Humans{public function __construct($name) {/*...*/}public function eat() { /*...*/}public function sleep() { /*...*/}public function snore() { /*...*/}public function wakeup() { /*...*/}}Marcus Börger Introduction to Object-oriented programming with PHP 21 Some Inheritanceclass Humans{public function __construct($name) { /*...*/}public function eat() { /*...*/}public function sleep() { /*...*/}public function snore() { /*...*/}public function wakeup() { /*...*/}}class WomenextendsHumans{public function giveBirth() { /*...*/}}Marcus Börger Introduction to Object-oriented programming with PHP 22 Inheritance+Polymorphismclass Humans{public function __construct($name) { /*...*/}public function eat() { /*...*/}public function sleep() { /*...*/}public function wakeup() { /*...*/}}class Womenextends Humans{public function giveBirth() { /*...*/}}class Menextends Humans{public function snore() { /*...*/}}Marcus Börger Introduction to Object-oriented programming with PHP 23 A little abstractionabstractclass Humans{public function __construct($name) { /*...*/}abstractpublic function gender();public function eat() { /*...*/}public function sleep() { /*...*/}public function wakeup() { /*...*/}}class Womenextends Humans{public function gender() { return 'female'; }public function giveBirth() { /*...*/}}class Menextends Humans{public function gender() { return 'male'; }public function snore() { /*...*/}}Marcus Börger Introduction to Object-oriented programming with PHP 24 A little abstractionabstract class Humans{public function __construct($name) { /*...*/}abstract public function gender();public function eat() { /*...*/}public function sleep() { /*...*/}public function wakeup() { /*...*/}}class Womenextends Humans{finalpublic function gender() { return 'f'; }public function giveBirth() { /*...*/}}class Menextends Humans{finalpublic function gender() { return 'm'; }public function snore() { /*...*/}}Marcus Börger Introduction to Object-oriented programming with PHP 25 PHP and OOPMarcus Börger Introduction to Object-oriented programming with PHP 26 PHP 4 and OOP ?Poor Object modelMethodsNo visibilityNo abstracts, no finalStatic without declarationPropertiesNo static propertiesNo constantsInheritanceNo abstract, final inheritance, no interfacesNo prototype checking, no typesObject handlingCopied by valueNo destructorsMarcus Börger Introduction to Object-oriented programming with PHP 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 IteratorsMarcus Börger Introduction to Object-oriented programming with PHP 28 Revamped Object ModelPHP 5 has really good OOP supportBetter code reuseBetter for team developmentEasier to refactorSome patterns lead to much more efficient codeFits better in marketing scenariosMarcus Börger Introduction to Object-oriented programming with PHP 29 PHP 5 OOP in detailMarcus Börger Introduction to Object-oriented programming with PHP 30 Objects referenced by identifiersObjects are no longer somewhat special arraysObjects are no longer copied by defaultObjects may be copied using clone/__clone()classObject {};$obj=newObject();$ref =$obj;$dup =clone $obj;Class Object$obj$ref$dupInstance 1Instance 2Marcus Börger Introduction to Object-oriented programming with PHP 31 Constructors and DestructorsConstructors/Destructors control object lifetimeConstructors may have both new OR old style nameNew style constructors are preferredConstructors must not use inherited protocolDestructors are called when deleting the last referenceNo particular or controllable order during shutdownDestructors cannot have parametersSince PHP 5.0.1 destructors can work with resourcesclassObject {function__construct() {}function__destruct() {}}$obj= newObject();unset($obj);Marcus Börger Introduction to Object-oriented programming with PHP 32 Constructors and DestructorsParents must be called manuallyclassBase {function__construct() {}function__destruct() {}}classObject extendsBase {function__construct() {parent::__construct();}function__destruct() {parent::__destruct();}}$obj= newObject();unset($obj);Marcus Börger Introduction to Object-oriented programming with PHP 33 Default property valuesProperties can have default valuesBound to the class not to the objectDefault values cannot be changed but overwrittenclassObject {var$prop ="Hello\n";}$obj1 = newObject;$obj1->prop ="Hello World\n";$obj2 = newObject;echo $obj2->prop; //HelloClass Object$prop/default$obj2Instance 2$prop$obj1Instance 1$propMarcus Börger Introduction to Object-oriented programming with PHP 34 Static membersStatic methods and propertiesBound to the class not to the objectOnly exists once per class rather than per instanceCan be initialized class Object {var$prop;static$stat ="Hello\n";staticfunction test() {echoself::$stat;} }Object::test();$obj1 = newObject;$obj2 = newObject;Class Object$stat$obj2Instance 2$prop$obj1Instance 1$propMarcus Börger Introduction to Object-oriented programming with PHP 35 Pseudo constants__CLASS__shows the current class name__METHOD__shows class and method or functionselfreferences the class itselfparentreferences the parent class$thisreferences the object itselfclassBase {static function Show() {echo __FILE__.'('.__LINE__.'):'.__METHOD__."\n";}}class Objectextends Base{static function Use() {Self::Show();Parent::Show();} static function Show() {echo __FILE__.'('.__LINE__.'):'.__METHOD__."\n";}}Marcus Börger Introduction to Object-oriented programming with PHP 36 VisibilityControlling member visibility /Information hidingA derived class doesn't know parents private membersAn inherited protected member can be made publicclassBase {public$a;protected$b;private$c;}classDerived extendsBase {public$a;public$b;private$c; }Base$a$b$cDerived$a$b$cBase::$cMarcus Börger Introduction to Object-oriented programming with PHP 37 Constructor visibilityA protected constructor prevents instantiationclassBase {protected function__construct() {}}classDerived extendsBase {//constructor is still protectedstatic function getBase() {return new Base; //Factory pattern}}class Threeextends Derived{public function__construct() {}}Marcus Börger Introduction to Object-oriented programming with PHP 38 The Singleton patternSometimes you want only a single instance of aclassto ever exist.DB connectionsAn object representing the user or connection.class Singleton{static private $instance;protected function __construct() {}final private function __clone() {}static function getInstance() {if(!self::$instance) self::$instance= new Singleton();return self::$instance;}}$a= Singleton::getInstance();$a->id= 1;$b= Singleton::getInstance();print $b->id."\n";Marcus Börger Introduction to Object-oriented programming with PHP 39 ConstantsConstants are read only static propertiesConstants are always publicclassBase {constgreeting ="Hello\n";}classDerviedextendsBase {constgreeting ="Hello World\n";static function func() { echo parent::greeting; }}echoBase::greeting;echoDerived::greeting;Derived::func();Marcus Börger Introduction to Object-oriented programming with PHP 40 Abstract membersMethods can be abstractThey don’t have a bodyA class with an abstract method must be abstractClasses can be made abstractThe class cannot be instantiatedProperties cannot be made abstractabstractclassBase {abstractfunctionno_body();}classDerived extendsBase {functionno_body() { echo"Body\n"; }}Marcus Börger Introduction to Object-oriented programming with PHP 41 Final membersMethods can be finalThey cannot be overwrittenThey are class invariantsClasses can be finalThey cannot be inheritedclassBase {finalfunctioninvariant() { echo"Hello\n"; }}classDerived extendsBase {}finalclassLeaf extendsDerived {}Marcus Börger Introduction to Object-oriented programming with PHP 42 Often different objects have the same interfacewithout having the same base classclassLine {functiondraw() {};}classPolygon {protected $lines;functiondraw() {foreach($this->linesas $line)$line->draw();}}classRectangle extendsPolygon {}classEllipse {functiondraw() {};}classCircle extendsEllipse {functiondraw() {parent::draw();}}Different Object same behaviorPolygonLineEllipseCircle$linesRectangleMarcus Börger Introduction to Object-oriented programming with PHP 43 InterfacesInterfaces describe an abstract class protocolClasses may inherit multiple InterfacesinterfaceDrawable{functiondraw();}classLine implementsDrawable{functiondraw() {};}classPolygon implementsDrawable{protected $lines;functiondraw() {foreach($this->linesas $line)$line->draw();}}classRectangle extendsPolygon {}classEllipse implementsDrawable{functiondraw() {};}classCircle extendsEllipse {functiondraw() {parent::draw();}}DrawablePolygonLineEllipseCircle$linesRectangleMarcus Börger Introduction to Object-oriented programming with PHP 44 Property kindsDeclared propertiesMay have a default valueCan have selected visibilityImplicit public propertiesDeclared by simply using them in ANY methodVirtual propertiesHandled by interceptor methodsStatic propertiesBound to the class rather than to the instanceMarcus Börger Introduction to Object-oriented programming with PHP 45 Object to String conversion__toString(): semi-automatic object to stringconversion with echo and print(automatic starting with 5.2)classObject {function__toString() {return'Object as string';}}$o = newObject;echo $o; //does call __toString$str= (string) $o; //does call __toStringMarcus Börger Introduction to Object-oriented programming with PHP 46 InterceptorsAllow to dynamically handle non class membersLazy initialization of propertiesSimulating Object aggregation and Multiple inheritanceclassObject {protected $virtual = array();function__get($name) { return @$this->virtual[$name];}function __set($name, $value) {$this->virtual[$name] = $value;}function __unset($name) {unset($this->virtual[$name]);}function __isset($name) {return isset($this->virtual[$name]);}function __call($func, $params) {echo 'Could not call ' . __CLASS__ . '::' . $func. "\n";}}Marcus Börger Introduction to Object-oriented programming with PHP 47 TypehintingPHP 5 allows to easily force a type of a parameterPHP does not allow NULL for typehintsTypehints must be inherited as given in base classPHP 5.1 offers typehinting with arraysPHP 5.2 offers optional typehintedparameters (= NULL)classObject {public functioncompare(Object$other) {//Some code here}public function compare2($other) {if (is_null($other) || $otherinstanceofObject) {//Some code here} } }Marcus Börger Introduction to Object-oriented programming with PHP 48 Class DesignIt is important to think about your class hierarchyAvoid very deep or broad inheritance graphsPHP only supports is-aand has-arelationsVehicleTruckCarBusDieselGasolineEngineBicycleTiresTurbineTankPlaneMarcus Börger Introduction to Object-oriented programming with PHP 49 Too Strict or too Weak?PHP tries to prevent you from doing some errorsYou are bound to keep inherited signaturesYou cannot change from ref to non-ref returnYet PHP allows absolute flexibilityJust do not define a signatureWarning: This is extremely error proneMarcus Börger Introduction to Object-oriented programming with PHP 50 Dynamic class loadingMarcus Börger Introduction to Object-oriented programming with PHP 51 Dynamic class loading __autoload() is good Requires a single file for each classOnly load class files when necessaryNo need to parse/compile unneeded classesNo need to check which class files to loadAdditional user space codeOnly one single loader model is possible when you're aloneMarcus Börger Introduction to Object-oriented programming with PHP 52 __autoload& require_onceStore the class loader in an include fileIn each script:require_once('/autoload.inc')Use INI option:auto_prepend_file=/autoload.incMarcus Börger Introduction to Object-oriented programming with PHP 53 SPL'sclass loadingSupports fast default implementationLook into path's specified by INI option include_pathLook for specified file extensions (.inc, .php)Ability to register multiple user defined loadersOverwrites ZEND engine's __autoload() cacheYou need to register __autoloadif using spl'sautoloadMarcus Börger Introduction to Object-oriented programming with PHP 54 SPL'sclass loadingspl_autoload($class_name,$extensions=NULL)Load a class from a file in include pathFast c code implementationspl_autoload_extensions($extensions=NULL)Get or set filename extensionsspl_autoload_register($loader_function)Register a single loader functionspl_autoload_unregister($loader_function)Unregistera single loader functionspl_autoload_functions()List all registered loader functionsspl_autoload_call($class_name)Load a class through registered class loadersUses spl_autoload()as fallbackMarcus Börger Introduction to Object-oriented programming with PHP 55 ExceptionsMarcus Börger Introduction to Object-oriented programming with PHP 56 ExceptionsRespect these rules1.Exceptions are exceptions2.Never use exceptions for control flow3.Never ever use exceptions for parameter passingMarcus Börger Introduction to Object-oriented programming with PHP 57 Exception specializationExceptions should be specializedExceptions should inherit built in class exceptionclassYourExceptionextendsException {}try {//your codethrow newYourException();}catch (YourException$e) {//exception handling}catch (Exception$e) {//exception handling}Marcus Börger Introduction to Object-oriented programming with PHP 58 Exception specializationException blocks can be nestedExceptions can be re thrownclassYourExceptionextendsException { }try {try {//your codethrow newYourException();}catch (YourException$e) {//exception handlingthrow $e;}catch (Exception$e) {//exception handling}}catch (YourException$e) {//exception handling}Marcus Börger Introduction to Object-oriented programming with PHP 59 Practical use of exceptionsConstructor failureConverting errors/warnings to exceptionsSimplify error handlingProvide additional error information by taggingMarcus Börger Introduction to Object-oriented programming with PHP 60 Constructor failureIn PHP 4.4 you would simply unset($this)Provide an argument to receive the error conditionMarcus Börger Introduction to Object-oriented programming with PHP 61 Constructor failureIn 5 constructors do not return the created objectExceptions allow to handle failed constructorsMarcus Börger Introduction to Object-oriented programming with PHP 62 Convert Errors to ExceptionsImplementing PHP 5.1 class ErrorExceptionseverity= $errno;$this->file= $file;$this->line = $line;}function getSeverity() {return $this->severity;}}}?>Marcus Börger Introduction to Object-oriented programming with PHP 63 Convert Errors to ExceptionsImplementing the error handlerMarcus Börger Introduction to Object-oriented programming with PHP 64 Simplify error handlingTypical database access code contains lots of if'squery('SELECTdata');if ($res) {$res2= $db->query('SELECTother');if ($res2) {//handle data$ok= true; //only if all went ok}}}if (!$ok) echo 'Service currently unavailable
';?>Marcus Börger Introduction to Object-oriented programming with PHP 65 Simplify error handlingTrade code simplicity with a new complexitysetAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$res= $db->query('SELECTdata');$res2= $db->query('SELECTother');//handle data}catch (Exception $e) {echo'Service currently unavailable
';error_log($e->getMessage());}?>Marcus Börger Introduction to Object-oriented programming with PHP 66 SPL ExceptionsSPL provides a standard set of exceptionsClass Exception mustbe the root of all exceptionsMarcus Börger Introduction to Object-oriented programming with PHP 67 General distinguishingLogicExceptionAnything that could have been detected at compile time, during application designor by the good old technology: "look closely"RuntimeExceptionAnything that is unexpected during runtimeBase Exception for all database extensionsMarcus Börger Introduction to Object-oriented programming with PHP 68 LogicExceptionFunction not found or similarBadMethodCallExceptionValue not in allowed domainArgument not validLength exceededSome index is out of rangeMarcus Börger Introduction to Object-oriented programming with PHP 69 RunTimeExceptionAn actual value is out of boundsBuffer or other overflow situationValue outside expected rangeBuffer or other underflow situationAny other unexpected valuesMarcus Börger Introduction to Object-oriented programming with PHP 70 Overloading __callIf using __call, ensure only valid calls are madeabstract class MyIteratorWrapperimplements Iterator{function __construct(Iterator$it){$this->it= $it;}function __call($func, $args){$callee= array($this->it, $func); if (!is_callable($callee)) {throw new BadMethodCallException();}return call_user_func_array($callee, $args);}} Compile-Time:Error in designMarcus Börger Introduction to Object-oriented programming with PHP 71 Interfaces and __callInterface functions cannot be handled by __callEither mark the class abstract...abstractclass MyIteratorWrapperimplements Iterator{function __construct(Iterator$it){$this->it= $it;}function __call($func, $args){$callee= array($this->it, $func); if (!is_callable($callee)) {throw new BadMethodCallException();}return call_user_func_array($callee, $args);}}}Interface Iterator{function rewind();function valid();function current();function key();function next();Marcus Börger Introduction to Object-oriented programming with PHP 72 Interfaces and __callInterface functions cannot be handled by __call...or provide the functions (here as proxy/forward)class MyIteratorWrapperimplements Iterator{function __construct(Iterator$it){$this->it= $it;}function __call($func, $args){$callee= array($this->it, $func); if (!is_callable($callee)) {throw new BadMethodCallException();}return call_user_func_array($callee, $args);}function rewind(){ $this->it->rewind(); }function valid(){ return $this->it->valid(); }function current(){ return $this->it->current(); }function key(){ return $this->it->key(); }function next(){ $this->it->next(); }}}Interface Iterator{function rewind();function valid();function current();function key();function next();Marcus Börger Introduction to Object-oriented programming with PHP 73 Expecting formatted dataOpening a file for reading$fo= newSplFileObject($file);$fo->setFlags(SplFileObject::DROP_NEWLINE);$data =array();Run-Time:File might not be accessible or existMarcus Börger Introduction to Object-oriented programming with PHP 74 Expecting formatted dataReading a formatted file line by line$fo= new SplFileObject($file);$fo->setFlags(SplFileObject::DROP_NEWLINE);$data = array();foreach($foas$l) {if(/*** CHECK DATA ***/) {throw newException();}$data[] =$l; }!preg_match($regex,$l)UnexpectValueExceptioncount($l=split(',',$l)) !=3RangeExceptioncount($data) >100OverflowExceptionRun-Time:File might not be accessible or existRun-Time:data is different for every executionMarcus Börger Introduction to Object-oriented programming with PHP 75 Expecting formatted dataCehckingdata after pre-processing$fo= new SplFileObject($file);$fo->setFlags(SplFileObject::DROP_NEWLINE);$data = array();foreach($foas $l) {if (!preg_match('/\d,\d/', $l)) {throw new UnexpectedValueException();}$data[] = $l; }//Checks after the file was read entirelyif (count($data) < 10)throw new UnderflowException();if (count($data) > 99)throw new OverflowException();if (count($data) < 10 || count($data) > 99) throw new OutOfBoundsException();Run-Time:data is different for every executionRun-Time:Filemightnot be accessible or existMarcus Börger Introduction to Object-oriented programming with PHP 76 Expecting formatted dataProcessing pre-checked data$fo= new SplFileObject($file);$fo->setFlags(SplFileObject::DROP_NEWLINE);$data = array();foreach($foas $l) {if (!preg_match('/\d,\d/', $l)) {throw new UnexpectedValueException();}$data[] = $l; }if (count($data) < 10) throw new UnderflowException();//maybe more precessingcodeforeach($dataas &$v) {if (count($v) == 2) {throw new DomainException();}$v= $v[0] * $v[1]; }Compile-Time:exception signals failed preconditionRun-Time:data is different for every executionRun-Time:File might not be accessible or existMarcus Börger Introduction to Object-oriented programming with PHP 77 ReflectionMarcus Börger Introduction to Object-oriented programming with PHP 78 Reflection APICan reflect nearly all aspects of your PHP codeFunctionsClasses, Methods, PropertiesExtensionsclassFoo{public$prop;functionFunc($name) {echo"Hello $name";}}ReflectionClass::export('Foo');ReflectionObject::export(newFoo);ReflectionMethod::export('Foo','func');ReflectionProperty::export('Foo','prop');ReflectionExtension::export('standard');Marcus Börger Introduction to Object-oriented programming with PHP 79 Dynamic object creationReflection allows dynamic object creation class Test{function __construct($x, $y= NULL) {$this->x= $x;$this->y= $y;}}function new_object_array($cls, $args= NULL) { return call_user_func_array(array(newReflectionClass($cls),'newInstance'),$args);}new_object_array('stdClass');new_object_array('Test', array(1));new_object_array('Test', array(1, 2));Marcus Börger Introduction to Object-oriented programming with PHP 80 Built-in InterfacesMarcus Börger Introduction to Object-oriented programming with PHP 81 Built-in InterfacesPHP 5 contains built-in interfaces that allow you to change the way the engine treats objects.ArrayAccessIteratorIteratorAggregateBuilt-in extension SPL provides more Interfaces and ClassesArrayObject, ArrayIteratorFilterIteratorRecursiveIteratorUse CLI: php --re SPLphp --rcArrayAccessMarcus Börger Introduction to Object-oriented programming with PHP 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’.interface ArrayAccess{//@return whether $offset is valid (true/false)function offsetExists($offset);//@return the value associated with $offsetfunction offsetGet($offset);//associate $value with $offset (store the data)function offsetSet($offset, $value);//unset the data associated with $offsetfunction offsetUnset($offset);}Marcus Börger Introduction to Object-oriented programming with PHP 83 ArrayAccessArrayAccessdoes not allow references(the following is an error)class MyArrayextends ArrayAccess{function &offsetGet($offset) { /* ... */}function offsetSet($offset, &$value) { /* ... */}function offsetExists($offset) { /* ... */}function offsetUnset($offset) { /* ... */}}Marcus Börger Introduction to Object-oriented programming with PHP 84 ArrayAccess ExampleWe want to create variables which can be shared between processes.We will set up interception so that access attemptson the variable are actually performed through a DBM file.Marcus Börger Introduction to Object-oriented programming with PHP 85 Binding Access to a DBMdb= dba_open($file, 'cd', $handler))throw new exception('Could not open file '. $file);} function __destruct() { dba_close($this->db); }function offsetExists($offset) {return dba_exists($offset, $this->db);}function offsetGet($offset) {return dba_fetch($offset, $this->db);}function offsetSet($offset, $value) {return dba_replace($offset, $value, $this->db);}function offsetUnset($offset) { return dba_delete($offset, $this->db);}}?>Marcus Börger Introduction to Object-oriented programming with PHP 86 A Trivial ExampleMarcus Börger Introduction to Object-oriented programming with PHP 87 IteratorsNormal objects behave like arrays when used with the foreachconstructSpecialized Iterator objects can be iterated differentlyMarcus Börger Introduction to Object-oriented programming with PHP 88 What are IteratorsIterators are a concept to iterate anything that contains other things. Iterators allow to encapsulate algorithmsMarcus Börger Introduction to Object-oriented programming with PHP 89 What are IteratorsIterators are a concept to iterate anything that contains other things. Examples:Values and Keys in an arrayArrayObject, ArrayIteratorText lines in a fileSplFileObjectFiles in a directory[Recursive]DirectoryIteratorXML Elements or Attributesext: SimpleXML, DOMDatabase query resultsext: PDO, SQLite, MySQLiDates in a calendar rangePECL/date (?)Bits in an image?Iterators allow to encapsulate algorithmsMarcus Börger Introduction to Object-oriented programming with PHP 90 What are IteratorsIterators are a concept to iterate anything that contains other things. Examples:Values and Keys in an arrayArrayObject, ArrayIteratorText lines in a fileSplFileObjectFiles in a directory[Recursive]DirectoryIteratorXML Elements or Attributesext: SimpleXML, DOMDatabase query resultsext: PDO, SQLite, MySQLiDates in a calendar rangePECL/date (?)Bits in an image?Iterators allow to encapsulate algorithmsClasses and Interfaces provided by SPL:AppendIterator, CachingIterator, LimitIterator, FilterIterator, EmptyIterator, InfiniteIterator, NoRewindIterator, OuterIterator, ParentIterator, RecursiveIterator, RecursiveIteratorIterator, SeekableIterator, SplFileObject, . . . Marcus Börger Introduction to Object-oriented programming with PHP 91 Array vs. IteratorAn array in PHP$ar=array()can be rewound:reset($ar)is valid unless it's key is NULL:!is_null(key($ar))have current values:current($ar)have keys:key($ar)can be forwarded:next($ar)Something that is traversable$it = newIterator;mayknow how to be rewound:$it->rewind()(does not return the element)should know if there is a value:$it->valid()mayhave a current value:$it->current()mayhave a key:$it->key()(may return NULL at any time)can forward to its next element:$it->next()Marcus Börger Introduction to Object-oriented programming with PHP 92 The big differenceArraysrequire memory for all elements allow to access any element directlyIteratorsonly know one element at a timeonly require memory for the current elementforward access onlyAccess done by method callsContainersrequire memory for all elements allow to access any element directlycan create external Iterators or are internal IteratorsMarcus Börger Introduction to Object-oriented programming with PHP 93 The basic conceptsIterators can be internal or external also referred to as active or passiveAn internal iterator modifies the object itselfAn external iterator points to another object without modifying itPHP always uses external iterators at engine-levelIterators mayiterate over other iteratorsMarcus Börger Introduction to Object-oriented programming with PHP 94 PHP IteratorsAnything that can be iterated implements TraversableObjects implementing Traversablecan be used in foreachUser classes cannot implement TraversableIteratorAggregateis for objects that use external iteratorsIteratoris for internal traversal or external iteratorsIteratorAggregate+getIterator (): IteratorTraversableIterator+++++rewind ()valid ()current ()key ()next (): void: boolean: mixed: mixed: voidMarcus Börger Introduction to Object-oriented programming with PHP 95 Implementing IteratorsTraversableIteratorAggregate+getIterator (): IteratorIterator+++++rewind ()valid ()current ()key ()next (): void: boolean: mixed: mixed: voidAggregateImpl+<>getIterator (): IteratorIteratorImpl+++++<><><><><>rewind ()valid ()current ()key ()next (): void: boolean: mixed: mixed: voidMarcus Börger Introduction to Object-oriented programming with PHP 96 How Iterators workIterators can be used manuallyIterators can be used implicitly with foreachrewind();while($o->valid()) {$key=$o->key();$val=$o->current();//somecode$o->next();}?>$val) {//somecode}?>Marcus Börger Introduction to Object-oriented programming with PHP 97 rewind();$it->valid();$it->next()) {$value =$it->current();$key=$it->key();}?>How Iterators workInternal IteratorsUser IteratorsMarcus Börger Introduction to Object-oriented programming with PHP 98 Internal IteratorsUser Iterators$val) {//access data}?>How Iterators workMarcus Börger Introduction to Object-oriented programming with PHP 99 $val) {//access filtered data only}?>How Iterators workInternal IteratorsUser IteratorsMarcus Börger Introduction to Object-oriented programming with PHP 100 Debug Sessionar=$ar;}functionrewind() {rewind($this->ar);}fucntionvalid() {return !is_null(key($this->ar));}function key() {return key($this->ar);}fucntioncurrent() {return current($this->ar);}function next() {next($this->ar);}}?>$val) {echo "$key => $va\n";}?>0 => 11 => 22 => 3PHP 5.1Marcus Börger Introduction to Object-oriented programming with PHP 101 Why not just use arrays:foreach($some_arrayas $item) {/*...*/} 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 setsLazy InitializationDirectoriesAnything not already an arrayAren’t Iterators Pointless in PHP?Marcus Börger Introduction to Object-oriented programming with PHP 102 Iterators by exampleUsing Iterators you can efficiently grab all groups from INI filesThe building blocks:A class that handles INI files An abstract filter IteratorA filter that filters group names from the INI file inputAn Iterator to read all entries in the INI fileAnother filter that allow to search for specific groupsMarcus Börger Introduction to Object-oriented programming with PHP 103 INI file abstractionclass DbaReaderimplements Iterator{protected $db= NULL;private $key= false, $val= false;function __construct($file, $handler) {if (!$this->db= dba_open($file, 'r', $handler))throw new Exception("Couldnot open file $file");}function __destruct() {dba_close($this->db);}private function fetch_data($key) {if (($this->key =$key)!== false)$this->val= dba_fetch($this->key, $this->db);}function rewind() {$this->fetch_data(dba_firstkey($this->db));}function next() {$this->fetch_data(dba_nextkey($this->db));}function current() {return $this->val;}function valid() {return $this->key!== false; }function key() {return $this->key; }}Marcus Börger Introduction to Object-oriented programming with PHP 104 Filtering Iterator keysFilterIteraoris an abstract class Abstract accept() is called from rewind() and next()When accept() returns false next() will be called automaticallyrx= $regex;}function accept() {return ereg($this->rx,$this->getInnerIterator()->key());}function getRegex() {return $this->rx;}protected function __clone($that) {//disallow clone }}?> Marcus Börger Introduction to Object-oriented programming with PHP 105 Getting only INI groupsMarcus Börger Introduction to Object-oriented programming with PHP 106 Putting it to work2) {$it= new KeyFilter($it, $argv[2]);}foreach($itas $group) {echo $group. "\n";}?>Avoid calling __autoload()Marcus Börger Introduction to Object-oriented programming with PHP 107 Conclusion so farIterators require a new way of programmingIterators allow to implement algorithms abstracted from dataIterators promote code reuseSome things are already in SPLFilteringHandling recursionLimitingMarcus Börger Introduction to Object-oriented programming with PHP 108 Design PatternsMarcus Börger Introduction to Object-oriented programming with PHP 109 Let’s Talk About PatternsPatterns catalog solutions to problem categories They consist ofA nameA description of their problemA description of the solutionAn assessment of the pros and cons of the patternMarcus Börger Introduction to Object-oriented programming with PHP 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?Marcus Börger Introduction to Object-oriented programming with PHP 111 Patterns We’ve Seen So FarSingleton PatternIterator PatternFactory PatternMarcus Börger Introduction to Object-oriented programming with PHP 112 Aggregator PatternProblem: You have collections of items that you operate on frequently with lots of repeated code.Remember our calendars:foreach($entriesas $entry) { echo $entry;}Solution: Create a container that implements the same interface, and perfoms the iteration for you.Marcus Börger Introduction to Object-oriented programming with PHP 113 Aggregator Patternclass EntryAggregateextends Entry{protected $entries;...public function display() {foreach($this->entriesas $entry) {$entry->display();}public function add(Entry $e) {array_push($this->entries, $e);} }By extending Entry, the aggregate can actually stand in any place that entry did, and can itself contain other aggregated collections.Marcus Börger Introduction to Object-oriented programming with PHP 114 Proxy PatternProblem: You need to provide access to an object, 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.Marcus Börger Introduction to Object-oriented programming with PHP 115 Proxy Pattern in PEAR SOAPwsdl= WSDLManager::get($endpoint);} public function __call($method, $args) {$port= $this->wsdl->getPortForOperation($method);$this->endpoint=$this->wsdl->getPortEndpoint($port);$request= SOAP_Envelope::request($this->wsdl);$request->addMethod($method, $args);$data= $request->saveXML();return SOAP_Envelope::parse($this->endpoint,$data);}}?>Marcus Börger Introduction to Object-oriented programming with PHP 116 Observer PatternProblem: 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. Marcus Börger Introduction to Object-oriented programming with PHP 117 Object handling side notesYou cannot access the object identifier/handle$observers[] = $observer;YOU need to prevent double insertion/executionforeach($observersas$o) {if ($o ===$observer) return;}$observers[] =$observer;No easy way to delete an object from an arrayforeach($observersas$k =>$o) {if ($o ===$observer) {unset($observer[$k]);break;}}Marcus Börger Introduction to Object-oriented programming with PHP 118 Object Storageclass ObjectStorage{protected$storage = array();functionattach($obj) {foreach($this->storage as$o) {if ($o ===$obj) return;}$this->storage[] =$obj;}functiondetatch($obj) {foreach($this->storage as$k =>$o) {if ($o ===$obj) {unset($this->storage[$k]);return;}}}}Marcus Börger Introduction to Object-oriented programming with PHP 119 Object Storage in 5.2class ObjectStorage{protected$storage = array();functionattach($obj) {$this->storage[spl_object_hash($obj)] =$obj;}functiondetatch($obj) {unset($this->storage[spl_object_hash($obj)]);}}Or simply use SplObjectStorageMarcus Börger Introduction to Object-oriented programming with PHP 120 class MySubjectimplements Subject{protected $observers;public function __construct() {$this->observer= new ObjectStorage;}public function attach(Observer $o) {$this->observers->attach($o);}public function detach(Observer$o) {$this->observers->detach($o);}public function notify() {foreach($this->observersas $o) $o->update($this);}}class MyObserverimplements Observer{public function update(Subject$s) {//do logging or some other action}}Concrete Examples: logging facilities: email, debugging, SOAP message notifications.Observer Pattern ImplementationMarcus Börger Introduction to Object-oriented programming with PHP 121 At Last some HintsList of all SPL classes PHP 5.0.0php –r 'print_r(array_keys(spl_classes()));'Reflection of a built-in class PHP 5.1.2php --rcReflection of a function or method PHP 5.1.2php --rfReflection of a loaded extension PHP 5.1.2php --re Extension information/configuration PHP 5.2.2php--riMarcus Börger Introduction to Object-oriented programming with PHP 122 ReferenceEverythiningabout PHPhttp://php.netThese slideshttp://talks.somabo.deSPL Documentaion& Exampleshttp://php.net/~helly/php/ext/splhttp://cvs.php.net/php-src/ext/spl/exampleshttp://cvs.php.net/php-src/ext/spl/internalGeorge Schlossnagle AdvancedPHP ProgrammingAndiGutmans, StigBakken, DerickRethansPHP 5 Power Programming