PHP Application Design Part 01 - OOP in Full Effect

Embed Size (px)

Citation preview

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    1/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    PHP Appl ic at ion Design Par t 1 :

    OOP In Ful l Effec t

    - 1 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    2/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    IntroductionWelcome to part one of the "Application Design" series.

    This series intends to show you how to create extensible applications with reusable code.In this first part you will be introduced to OOP in PHP.

    This article is an overview of what PHP has to offer with respect to OOP, with exampleson how to use these concepts.

    If you have wanted to grasp OOP, but haven't come around to learning it, this article isfor you. If you've read some "Hello World" in OOP tutorial, gotten familiar with OO syntaxbut are interested in learning more, this article is for you too.

    PHP 5 has been released for quite some time, putting more stress on Object Orientateddevelopment for PHP. PHP 5 comes with a new object model, a lot faster and adding a lotof new features. There are workarounds to mimic some of these features in PHP 4, someof which are covered in this article. Nevertheless, the main focus is on PHP5.

    PrerequisitesKnowledge of PHP and PHP syntax at an intermediate level is assumed.

    - 2 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    3/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    Index

    Index .................................................................................................................3Prerequisites .......................................................................................................2

    Introduction ........................................................................................................21. General PHP OOP and Syntax.............................................................................4

    1.1 Classes.......................................................................................................51.2 Inheritance .................................................................................................61.3 Constructors................................................................................................71.4 Scope Resolution Operator ............................................................................81.5 Abstract Classes ........................................................................................ 111.6 Magic Methods........................................................................................... 12

    2. PHP 5 ........................................................................................................... 132.1 Object Handles .......................................................................................... 132.2 Interfaces ................................................................................................. 132.3 Autoload................................................................................................... 142.4 Destructors ............................................................................................... 152.5 Visibility.................................................................................................... 152.6 Class Constants ......................................................................................... 162.7 Type Hinting.............................................................................................. 172.8 Exceptions ................................................................................................ 182.9 The Final Keyword...................................................................................... 192.10 More Magic Methods ................................................................................. 19

    2.10.1 Object Overloading ............................................................................. 192.10.2 Object cloning .................................................................................... 202.10.3 Other ................................................................................................ 22

    2.11 Object Iteration ....................................................................................... 233. Applying OOP Principles................................................................................... 25In conclusion ..................................................................................................... 28

    - 3 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    4/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    1. General PHP OOP and SyntaxObject Oriented Programming, originating in the 60s, wasnt used in mainstreamsoftware application development until the 1990s. So what is an object? In a definition

    proposed by G. Booch in 1991:

    An object is an instance of a class with the following essential properties:

    Each object has its own identity.Each object can have certain behaviour.Each object is in a state.

    Lets do a quick elaboration on these properties.

    Each object has its own identity.

    Each object persists in its own memory address. Meaning no two objects can be thesame. Objects are contained within variables; this is no different from other types ofvariables.

    Each object can have behaviour.

    This behaviour is used, thus this is also referred to as offer services. Basically an objecthas functions and variables local to that object, referred to as methods and properties(more on that in the next section), which define and influence this behaviour.

    Each object is in a state.The before mentioned properties (local variables) define the state an object is in. Thisstate can influence the behaviour (the methods act differently depending on theproperties). In addition, objects usually represent some concept, an object in the more

    literal sense.

    I know you all cant stand all this abstract talk and are itching for a code example, sohere we go

    Instantiating an (creating a new, unique) object:

    $someVariable = &new SomeClassDefiningAnObject;

    Note: PHP 4 requires that you use return by reference (&) to avoid multiple copies of the

    object. In PHP 5, this has been eliminated, see section2.1 Object Handles.

    Executing an embedded function (method):

    $someVariable->someMethod($someArgumentJustLikeARegularFunction );

    Capturing a return value from a method:

    $returnValue = $someVariable->someMethodThatReturnsSomething();

    - 4 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    5/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    Setting and retrieving the current value of a local variable (property):

    $someVariable->someProperty = 'SomeValue';

    $currentValue = $someVariable->someProperty;

    Ok, now you should have a basic understanding of what objects are and how to operateon them. Next were looking at defining the state and behaviour of objects: classes.

    1.1 ClassesYou pretty much already know what classes are: the definition of an object. Also referredto as a stateless object or object blueprint, the class defines how the object will lookafter first instantiation, and how it will behave in response to operating on it. However italso possible to operate within the scope of a class without an instantiation. You will readmore about that in the Scope Resolution Operator section.

    Consider this extremely simple example of a class:

    //PHP4

    class Dog {

    var $hungry = 'hell yeah.';

    function eat($food){

    $this->hungry = 'not so much.';

    }

    }

    $this is a reserved variable name, referring to the current instantiation of the object. By

    instantiating, we create a new Dog.

    $dog = &new Dog

    The initial state of this dog is that it is pretty hungry.

    echo $dog->hungry;

    Echoes:

    hell yeah.

    So we feed our newly instantiated dog a treat, to modify its state.

    $dog->eat('cookie');

    Yep, doggie isnt as hungry as before:

    - 5 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    6/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    echo $dog->hungry;

    Will echo:

    not so much.

    Doggie is happy enough, moving on.

    1.2 InheritanceClasses can have parent and child classes. When an object is instantiated by name of achild class, PHP looks for parent classes and starts combining the declarations, from thetop, to create the initial object. This is called inheritance. It isnt such a hard concept tograsp: a child inherits anything from its parents and ancestors that isnt redefined on theway down. If a class lower in the chain has a property or method with the same name as

    one higher in the chain, the last declaration is used for requests to the object.

    The way PHP is informed that a class has a parent class is with the extends keyword.

    Like with most popular languages, in PHP one class can only extend a single other class.An infinite number of classes can be derived from (extending) a single class though.

    A simple example:

    //PHP4

    class Animal {

    var $hungry = 'hell yeah.';

    function eat($food){

    $this->hungry = 'not so much.';

    }

    }

    class Dog extends Animal {

    function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    }

    Method eat is overwritten, because doggie only likes cookies. On the other hand,

    because all animals are hungry when you dont feed them, the initial state of $hungry

    need not be defined in Dog. The fictional Bird, Cat and Piggy could all extend Animal.

    Class Animal is unaware of the fact that it is being extended; there are no references to

    Dog whatsoever. Say Animal extended another class called LifeForm, and I instantiated

    Animal, only methods and properties ofAnimal and LifeForm would be included in theobject.

    - 6 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    7/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    1.3 ConstructorsConstructors are a way to define the default behaviour (set the default state) uponinstantiation. You can, as shown in the previous example, define the default state bysetting default values for properties. A constructor is nothing more than a method that isexecuted when instantiating an object. This is referred to as initializing the object.

    An object isnt fully initialized, constructed, until the constructor method has completed(if present). A constructor method isnt required, our previous examples worked just finewithout them. Another thing that should be noted is that only the constructor of the classused to instantiate is called automatically, any parent constructors need to be calledexplicitly.

    PHP 4 and 5 use different naming for constructors. PHP 4 will look for a method with thesame name as the class, PHP 5 uses the__constructmagic method. The PHP 4 method

    works in PHP 5 too, for backwards compatibility.

    //PHP4class Dog extends Animal {

    var $breed;

    function Dog($breed){

    $this->breed = $breed;

    }

    function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }}

    Instantiating a Dog requires us to specify its breed. The property breed is assigned a

    new value by cause of this initialization (previously NULL), and we have a Dog which

    initial state specifies its breed:

    $dog = &new Dog('Golden Retriever');

    We could change its breed afterwards if wed like:

    $dog->breed = 'Bloodhound';

    - 7 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    8/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    1.4 Scope Resolution OperatorOfficially called Paamayim Nekudotayim(Hebrew for double colon, now you know whatthe parser is talking about when you get errors), the scope resolution operator (::)

    allows you to perform static calls to methods and class members.

    Static methods can be called without requiring an instantiation. This can be useful bothinside a class declaration as outside of it.

    After an object is created, some reference to the overwritten methods and propertiesremains intact. One can access these methods from within the object statically (no newinstantiation is required, yet the object from within you are operating is still affected.).

    //PHP4

    class Animal {

    var $hungry = 'hell yeah.';

    function Animal(){

    echo 'I am an animal.';

    }

    function eat($food){

    $this->hungry = 'not so much.';

    }

    }

    class Dog extends Animal {

    var $breed;

    function Dog($breed){

    $this->breed = $breed;

    Animal::Animal();

    }

    function eat($food){

    if($food == 'cookie'){

    Animal::eat($food);

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    }$dog = new Dog('Rotweiler');

    $dog->eat('cookie');

    echo $dog->hungry;

    Dog is using its parents method eat to refer to the declaration ofeat that was

    overwritten by its own declaration ofeat. You need not specify the specific class name

    like in the above example to refer to the last declaration of a method (or property), the

    parentkeyword will point to that reference:

    parent::eat($food);

    - 8 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    9/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    Should you have multiple levels of inheritance, and want to address a declaration otherthan the one last defined, youll have to specify the class like in the above example class.

    The constructor of parent classes isnt called upon instantiation, so if we desire to run aparent constructor, we have to call it explicitly:

    Animal::Animal();

    Trying to call a method statically which has references to object specific variables (makes

    use of$this) from outside of the object, will throw an error:

    Dog::eat('cookie');

    Result:

    Fatal error: Using $this when not in object context

    PHP 5 introduces static class members. If you are unfamiliar with static variables, have athorough read on Variable Scope in the manual.

    Because all examples so far have been in PHP 4, Ill first show you a neat trick to mimicstatic class member behaviour in PHP 4.

    //PHP4

    class Dog{

    function &staticHungry($value = null){static $hungry;

    if($hungry === null){

    //$hungry not initialized yet, do so now.

    $hungry = 'hell yeah.';

    }

    elseif($value !== null) {

    $hungry = $value;

    }

    return $hungry;

    }

    }

    //Echo initial value:

    echo Dog::staticHungry();echo '
    ';

    //Set new value and echo it:

    echo Dog::staticHungry('not so much.');

    Its rather simple, actually. We make use of the fact that PHP 4 does allow staticvariables in the function scope, and wrap a method around a static variable to allowsetting and fetching of the value. Its patchy, but it works.

    Luckily, PHP 5 features static class members. In strict error mode (in PHP6 this is

    included in E_ALL) it also requires you to define what methods can be used statically.

    - 9 -

    http://nl2.php.net/manual/en/language.variables.scope.phphttp://nl2.php.net/manual/en/language.variables.scope.php
  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    10/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    //PHP5

    class Dog{

    static $hungry = 'hell yeah.';

    static function eat($food){

    if($food == 'cookie'){

    self::$hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    }

    Dog::eat('cookie');

    echo Dog::$hungry;

    Note the selfkeyword. It is simply referring to this class declaration. Like with theparent keyword, alternatively one could use the actual name of the class (Dog).

    In part three of this series youll find a very useful pattern making use of static classmembers, the Singleton pattern.

    Were still a mile away from that, so lets move on.

    - 10 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    11/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    1.5 Abstract ClassesAbstract classes are, well, abstract. An abstract class isnt intended to be instantiated,but to serve as parent to other classes, partly dictating how they should behave. Abstractclasses can have abstract methods, these are required in the child classes.

    Abstract classes can be used to enforce a certain interface.

    An example:

    //PHP5

    abstract class Animal {

    public $hungry = 'hell yeah.';

    abstract public function eat($food);

    }class Dog extends Animal{

    function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    }

    $dog = new Dog();

    echo $dog->hungry; //echoes "hell yeah."$dog->eat('peanut'); //echoes "barf, I only like cookies!"

    Never mind the public keyword for now.

    This might seem like strictly a PHP 5 thing, but abstract classes can easily be created inPHP 4 also. A simplified example:

    //PHP4

    class Animal {

    var $hungry = 'hell yeah.';

    function Animal(){

    trigger_error('"Animal" is an abstract class.',E_USER_ERROR);

    }

    function eat($food){

    trigger_error('Abstract method "eat" not implemented.',E_USER_ERROR

    );

    }

    }

    - 11 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    12/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    1.6 Magic MethodsMagic methods are simply reserved method names that are called when a certain eventoccurs. Like__construct in PHP 5 is called upon instantiation. There are two magic

    methods supported by PHP 4:__sleep and__wakeup. These are called uponserialization, un-serialization of objects.

    This is particularly useful if your object depends on some resource, like a databaseconnection, as they cannot be serialized.

    PHP 5 supports a number of extra magic methods, described in section 2.10 More MagicMethods.

    - 12 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    13/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    2. PHP 5By now you know that PHP 5 has many features PHP 4 lacks, it this chapter Ill go intothose features. If you have no interest in PHP 5 (how can you not!) you can skip this

    chapter.

    2.1 Object HandlesIn PHP 4 all variables of type object needed to be passed by reference, in order to avoidcopies when operating on it. In PHP 5, objects are defined by handles, like with resourcetype variables.

    Passing an object to a function doesnt make a copy of it. The by reference operator (&)becomes obsolete for this purpose.

    Have a read on References Explained if youre still a little confused by this.

    2.2 InterfacesPHP 5 features interfaces. Not to be confused with interfaces in the more general sense,the interface keyword creates an entity that can be used to enforce a common interfaceupon classes without having to extend them like with abstract classes. Instead aninterface is implemented.

    Interfaces are a lot different from abstract classes. For one, theyre not actually classes.They dont define properties, and they dont define any behaviour. The methods declaredin an interface must be declared in classes that implement it.

    Because an interface in the more general sense is a definition of how an object interactswith other code, all methods must be declared public (see section on visibility in thischapter). An abstract method can have any visibility, but the extending classes musthave their implementations use the same (or weaker) visibility. Implementing aninterface adds the methods as abstract methods to the subject class, failure toimplement it will result in an error like the following:

    Fatal error: Class SomeConcreteClass contains n abstract method(s) and

    must therefore be declared abstract or implement the remaining methods

    Yes, abstract classes can implement interfaces.

    Interfaces can be looked upon as a contract, a certificate of compliance if you will. Othercode is guaranteed that a class implementing it will use certain methods to interact.

    Enough babbling, lets see a code example:

    - 13 -

    http://nl2.php.net/manual/en/language.references.phphttp://nl2.php.net/manual/en/language.references.php
  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    14/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    //PHP5

    interface Animal {

    public function eat($food);

    }

    interface Mammal {

    public function giveBirth();

    }

    class Dog implements Animal, Mammal{

    public $gender = 'male';

    function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    function giveBirth(){

    if($this->gender == 'male'){

    echo 'I can\'t, I am a boy :P';

    }

    else {

    echo 'I\'m not even pregnant yet.';

    }

    }

    }

    Doggie implements 2 interfaces, both Animal and Mammal. You can implement as manyinterfaces as you like.

    2.3 AutoloadA very convenient feature,__autoload allows you to get rid of all those annoying

    includes that need to be managed. This magic function will execute whenever a class orinterface is referenced that hasnt been defined. That gives you the opportunity toinclude it.

    Following a standard class and directory naming scheme, heres a simple example of howthat might look:

    //PHP5function__autoload($className) {

    $file = 'lib/'.$className. '.class.php';

    if(!file_exists($file)){

    return false;

    }

    else {

    include $file;

    }

    }

    We dont need include_once, because once the file is included,__autoload will not

    trigger on that class or interface reference again. Note that__autoload can also beconfined to the scope of a class or object.

    - 14 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    15/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    2.4 DestructorsDestructors are another type of magic methods. Indicated by__destruct, these

    methods are called when all references to their objects are removed. This includes

    explicit un-setting and script shutdown. A quick example of this:

    //PHP5

    class Example {

    function__destruct() {

    echo 'Destructing object.';

    }

    }

    $objectOne = new Example();

    $objectTwo = new Example();

    unset($objectOne);

    echo 'Script still running.'

    This echoes:

    Destructing object.

    Script still running.

    Destructing object.Object one is destructed when we explicitly unset it, object two just before the scriptexecution is completed. An objects destructor is always executed. Note that if we had

    created a second object from within class Example, its destructor would also have been

    executed, as it would have removed all references to the embedded object.

    2.5 VisibilityPHP 5 allows you to declare the visibility of methods and properties. There are three

    types of visibility: public, protected and private.

    Public

    Public methods and properties are visible (accessible) to any code that queries them. Noaccessibility restrictions are applied. In PHP 4 all methods and properties are public. InPHP 5, methods without visibility declaration are assumed public, the visibility declarationis required for object properties (so that excludes static and constant class members).

    Protected

    Requests are only allowed from within the objects blueprint (that includes parent andchild classes). Meaning the following would fail:

    - 15 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    16/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    //PHP5

    class Teeth {

    protected $colour = 'white';

    public function stain(){

    $this->colour = 'yellow';

    }

    }

    class Dog {

    public $teeth;

    public function__construct(){

    $this->teeth = new Teeth();

    }

    public function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    //Attempt to turn teeth green:

    $this->teeth->colour = 'green';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    }

    $dog = new Dog();

    Produces:

    Fatal error: Cannot access protected property Teeth::$colour

    Should Teeth have been a parent class of Dog instead of a member object (class Dog

    extends Teeth bad practice), $colour would have been accessible though $this, but

    also statically by Teeth::$colour (or parent::$colour).

    Private

    Access is limited to the defining class (the class used to instantiate). No external accesswhatsoever is allowed.

    One thing that should be noted when using protected or private properties, is that if youattempt to assign a value to a property that isnt visible to the class you are doing it in,you will be creating a new property instead of resetting the original. Keep that in mindwhen you get unexpected values: check the propertys visibility.

    2.6 Class ConstantsWe already covered using static class members in PHP 5, there is another type of classmember, which we havent covered: class constants.

    I am assuming you are already familiar with regular constants, and are aware of howthey differ from variables.

    - 16 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    17/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    Class constants are just regular constants, confined to a class declaration. Becauseconstants are unchangeable, they are independent of any state the object could be in.Therefore they can only be called statically.

    //PHP5class Dog {

    const NUMBER_OF_LEGS = '4';

    public function__construct(){

    echo 'I have '.self::NUMBER_OF_LEGS.' legs,

    and you can\'t take that away from me!';

    }

    }

    $dog = new Dog();

    Both $dog->NUMBER_OF_LEGS and $this->NUMBER_OF_LEGS would have PHP looking for anon-existent object property: $NUMBER_OF_LEGS.

    2.7 Type HintingPHP 5 features type hinting as a means to limit the types of variables that a method willaccept as an argument. Lets kick off with a simple example:

    //PHP5

    class Rabbit {

    }class Feeder {

    public function feedRabbit(Rabbit $dog, $food){

    $dog->eat($food);

    }

    }

    class Dog {

    public function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {echo 'barf, I only like cookies!';

    }

    }

    }

    $dog = new Dog();

    $feeder = new Feeder();

    $feeder->feedRabbit($dog, 'broccoli');

    Attempting to use an instance of Dog with the feedRabbit method results in the

    following error:

    Fatal error: Argument 1 passed to Feeder::feedRabbit() must be an instanceof Rabbit

    - 17 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    18/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    However, type hinting allows a more generic use. Consider the following example:

    //PHP5

    class Animal {

    }

    class Feeder {

    public function feedAnimal(Animal $animal, $food){

    $animal->eat($food);

    }

    }

    class Dog extends Animal {

    public function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }

    }

    $dog = new Dog();

    $feeder = new Feeder();

    $feeder->feedAnimal($dog, 'broccoli');

    Because $dog is not only a Dog, but also an Animal, the requirement is met. Doggie

    doesnt like broccoli (who does?), but that is besides the point. Currently PHP only

    supports type hinting with objects and arrays.

    Note : since PHP 5.2, failing type hinting requirements result in a E_RECOVERABLE_ERROR typeerror, not an immediate fatal error.

    2.8 ExceptionsPHP 5 introduces the concept ofexceptions to PHP. An exception is not an error, anuncaught exception is (a fatal error).

    Using exceptions you will need the following keywords: try, throw and catch. PHP 5 has

    its build-in Exception class, which you can extend, but for this simple example I will

    stick to using the standard Exception class.

    - 18 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    19/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    try {

    $statement = 'Doggie likes broccoli.';

    echo $statement;

    if($statement == 'Doggie likes broccoli.'){

    throw new Exception('liar!');

    }

    //We escape from the try block as soon as an exception is thrown.

    echo 'Doggie won\'t speak these words.';

    }

    catch(Exception $e) {

    echo 'Caught exception of type Exception: "'

    .$e->getMessage().'". We know doggie only likes cookies.';

    }

    The code in the try block is executed until an exception is thrown. If an exception is

    thrown, the code in the corresponding catch block is executed. If there isnt acorresponding catch block, the exception is uncaught, resulting in a fatal error.

    2.9 The Final KeywordThe final keyword indicates that the declaration following it is final, no child class will be

    able to redefine it. One can declare both a single method or a whole class as final. If thewhole class is declared final, it becomes un-extendable: no child classes are allowed.

    There really isnt any more to it, apply it only if you are absolutely sure you dont wantthat specific class or method re-declared or extended.

    2.10 More Magic MethodsI already covered__construct,__destruct,__autoload, __sleep and__wakeup,

    heres a list of the rest of the magic methods, all of them new in PHP 5:

    Overloadingo __callo __geto __seto __isseto __unset

    Object cloningo __clone

    Othero __toStringo __setState

    2.10.1 Object OverloadingObject overloading refers to the mechanism where a call to a method or property will

    overload the call to a different property or method. The call ultimately made can dependon the type of the arguments or the context, making this another type ofpolymorphism.

    These magic methods allow you catch calls to methods and properties that havent beendefined, because you didnt know (or didnt want to specify) the exact name.

    The magic methods are executed only if the object doesnt have the method or propertydeclared.

    - 19 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    20/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    The following example class uses__set to check if an embedded object does have the

    property requested, before creating a new property for the parent object.

    //PHP5class DomXml

    {

    private $domDoc;

    public function__construct() {

    $this->domDoc = new DOMDocument();

    }

    private function__set($name,$value){

    //Overload.

    if(property_exists($this->domDoc,$name)){

    //Set DOMDocument value.

    $this->domDoc->$name = $value;

    }else {

    //Create new DomXml property.

    $this->$name = $value;

    }

    }

    }

    An example__call use:

    private function__call($name,$params){

    //Overload method call.if(method_exists($this->doc,$name)){

    return call_user_func_array(

    array($this->doc,$name),$params);

    }

    else {

    //Overloading produced unusable result.

    throw new DomXmlException(

    'Call to undeclared method "'.$name.'".');

    }

    }

    Methods__get,__isset and__unset have similar uses.

    2.10.2 Object cloning

    Because in PHP 5 objects use handles, if you would want to create a copy of an objectyou have to explicitly indicate so with the clone keyword.

    $obj = new Example();

    $objectCopy = clone $obj;

    Above gives you a new object that is an exact copy of$obj in the state it was when

    copied.

    - 20 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    21/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    The__clone method is triggered by this clone keyword. This allows you, for example, to

    ensure embedded objects are also cloned (otherwise they would this use the same objecthandle for the embedded objects).

    The following example illustrates this:

    //PHP5

    class Teeth {

    public $colour = 'white';

    }

    class Dog {

    public $teeth;

    public function__construct(){$this->teeth = new Teeth();

    }

    }

    $Lassie = new Dog();

    $Snoopy = clone $Lassie;

    $Snoopy->teeth->colour = 'green';

    echo $Snoopy->teeth->colour.'
    ';

    echo $Lassie->teeth->colour.'
    ';

    That will echo:

    green

    green

    Changing the property colour to green on $Snoopys teeth, also changes $Lassies teeth

    to green, because they share the same teeth. Imagine that, two dogs attached at themouth

    To give Lassies clone Snoopy its own set of teeth, we can use the __clone method:

    - 21 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    22/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    /PHP5

    class Teeth {

    public $colour = 'white';

    }

    class Dog {

    public $teeth;

    public function__construct(){

    $this->teeth = new Teeth();

    }

    public function__clone(){

    $this->teeth = clone $this->teeth;

    }

    }

    $Lassie = new Dog();

    $Snoopy = clone $Lassie;

    $Snoopy->teeth->colour = 'green';

    echo $Snoopy->teeth->colour.'
    ';

    echo $Lassie->teeth->colour.'
    ';

    Now it outputs:

    green

    white

    Voila, a cloned Dog now has its own teeth.

    Keep in mind that at times you may require that two objects do use the same embeddedobject.

    2.10.3 OtherOther methods that dont fit in the previous categories.

    __toString: Similar to__sleep and__wakeup, this magic method can be used to define

    how an object will present itself if the whole object is treated as a string.

    Example:

    class Dog{

    function __toString(){

    return 'I am Dog.';

    }

    }

    $dog = new Dog();

    echo $dog;

    - 22 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    23/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    The Dog object speaks:

    I am Dog.

    __set_state: This is a static method that can be used to reinitialize an object afterbeing flattened by var_export.

    2.11 Object IterationPHP allows objects to be iterated, all properties visible to the scope the iteration isrequested from are used. For PHP 4 users that means every single one. For PHP 5 thatsimply means any property that is available to the code iterating. Example of this with a

    foreach loop:

    //PHP4

    class Example {

    var $propertyOne = 'value1';

    var $propertyTwo = 'value2';

    var $propertyThree = 'value3';

    }

    $example = new Example();

    foreach($example as $property=>$value){

    echo 'Property "'.$property.'" has a value of "'.$value.'"
    ';

    }

    Output:

    Property "propertyOne" has a value of "value1"

    Property "propertyTwo" has a value of "value2"

    Property "propertyThree" has a value of "value2"

    Slightly more complex, on PHP 5 the visibility is taken into account:

    - 23 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    24/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    //PHP5

    class ExampleParent {

    protected $propertyOne = 'value1';

    public $propertyTwo = 'value2';}

    class Example extends ExampleParent {

    private $propertyThree = 'value3';

    public function__construct(){

    foreach($this as $property=>$value){

    echo 'Internal iteration of Example: Property "'

    .$property.'" => "'.$value.'"
    ';

    }

    echo '
    ';

    }

    }

    $example = new Example();

    foreach($example as $property=>$value){

    echo 'External iteration of Example: Property "'

    .$property.'" => "'.$value.'"
    ';

    }

    echo '
    ';

    $exampleParent = new ExampleParent();

    foreach($exampleParent as $property=>$value){

    echo 'External iteration of ExampleParent: Property "'

    .$property.'" => "'.$value.'"
    ';

    }

    Output:

    Internal iteration of Example: Property "propertyThree" => "value3"

    Internal iteration of Example: Property "propertyOne" => "value1"

    Internal iteration of Example: Property "propertyTwo" => "value2"

    External iteration of Example: Property "propertyTwo" => "value2"

    External iteration of ExampleParent: Property "propertyTwo" => "value2"

    - 24 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    25/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    3. Applying OOP PrinciplesThere are several heavily discussed OOP principles, the three most common of which Iwill show how to apply in this chapter:

    Inheritance Polymorphism Encapsulation

    Remember these classes?

    //PHP4

    class Animal {

    var $hungry = 'hell yeah.';

    function eat($food){$this->hungry = 'not so much.';

    }

    }

    class Dog extends Animal {

    function eat($food){

    if($food == 'cookie'){

    $this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like cookies!';

    }

    }}

    I used them to explain the concept of inheritance to you. Class Dog inherits Animals

    properties and methods when an object is instantiated, if it doesnt re-declare themitself.

    Animal could be the base class for other animal classes, like Bird and Cat. Subclasses

    like these would have a common interface defined by Animal. Confused? Sharing an

    interface simply means other components of your application can interact with theclasses in a similar way. This interaction is defined by the calling routines (methods and

    method arguments).

    In this ridiculously simply example, eat is the whole of the interface. Any class

    extending Animal is guaranteed to have a eat method which takes a single argument,

    because even if they dont declare it themselves, Animal defines the default behaviour!

    Lets take a look at a possible Bird

    - 25 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    26/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    //PHP4

    class Bird extends Animal {

    function eat($food){

    if($food == 'seed'){$this->hungry = 'not so much.';

    }

    else {

    echo 'barf, I only like seed!';

    }

    }

    }

    As you can see, Bird isnt all that different from Dog. They both eatfood. However,

    because they are not the same type ofAnimal, they behave differently in response to the

    $food they are being fed. This is referred to as having their own implementations of the

    interface provided by Animal, or simply: implementations ofAnimal.

    This is at the core of the principle ofpolymorphism: Different types of objects can behandled in the same way, even though their implementations vary.

    Object orientated programming promotes modularity by encapsulation. Encapsulationhides information about one part of your application from other parts. Again, this reallycomes down to implementing a solid interface. To make your application modular, youwill have to protect different parts from depending on specific implementations of otherparts. That was a mouth full, but the bottom line is you have to separate the differentconcepts involved in the processing.

    This practice is popularly known as separation of concerns. You try not to make a classthat has more than one concern, is handling more than one concept.

    Say I was building a framework, and currently creating a module to handle XML. Id likeseveral convenience methods, depending on the type (implementation) of XML (XHTML,RSS or XSL). I COULD simply add all of these class members related to a certainimplementation of XML to one single class. But it could quickly become a very large andhard to manage class. Also, if I decide to add more types of XML as an afterthought, orsimply because they werent near the top of the priority list, Id have to go in and editthe code that might influence how the other types are handled.

    Furthermore, what if I decide to use different parser? Id have to edit virtually every line

    of code in the class!

    Instead, lets separate the XML implementation from the method of parsing. One waythis could be accomplished is through inheritance, but that could easily create manysubclasses. Example with the previously mentioned types of XML plus the handlers DOMand SimpleXML:

    Xml_Dom Xml_Dom_Xhtml extends Xml_Dom Xml_Dom_Rss extends Xml_Dom Xml_Dom_Xsl extends Xml_Dom Xml_SimpleXML Xml_SimpleXML_Xhtml extends Xml_SimpleXML Xml_SimpleXML_Rss extends Xml_SimpleXML Xml_SimpleXML_Xsl extends Xml_SimpleXML

    - 26 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    27/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    Count: 8 classes. Not to mention *_SimpleXML_Xhtml and its siblings perform similar

    tasks as their *_Dom counterparts, meaning I have to edit two files instead of one if I

    decide to change how a specific XML implementation is handled.

    Instead, it is preferable to encapsulate the implementation, and have both methods ofparsing follow a common interface. This makes the implementation independent of themethod of parsing (the parser extension used).

    Xml_Document_Dom Xml_Document_SimpleXml Xml_Implementation_Xhtml Xml_Implementation_Rss Xml_Implementation_Xsl

    Count: 5 classes. More importantly, if I decide to change how RSS files are handled, Ionly have to change ONE class.

    Example client code:

    //PHP5

    $doc = new Xml_Document_Dom;

    $doc->setDTDDir('/lib/Xml/dtd');

    $doc->loadXml(file_get_contents('test.xml'));

    $doc->setImplementation(new Xml_Implementation_XHtml('transitional','utf-

    8'));

    $doc->validate();

    $xsldoc = new Xml_Document_SimpleXml;

    $xsldoc->setDTDDir('/lib/Xml/dtd');

    $xsldoc->setImplementation(new Xml_Implementation_Xsl());

    The implementation has been encapsulated in a property of the document object,allowing the same implementation classes to be used for different methods of parsing.

    Also thanks to the fact that Xml_Document_DomandXml_Document_SimpleXml have a

    common interface. This is called decoupling, more about that in part 3.

    - 27 -

  • 8/3/2019 PHP Application Design Part 01 - OOP in Full Effect

    28/28

    PHP Application Design Part 1: OOP in Full Effect 448191 - PHPFreaks.com

    In conclusionIf you were new to OOP, you probably learned a lot reading this article. If you were not,and this is all dull and boring to you, get ready for part 2 and 3, things just might get a

    little more interesting. :)

    If you have any comments about the content of this article, you can notify me byemailing johnkleijn at the free email service provided by Google, or send me a PM onthe PHPFreaks forums.

    If you have QUESTIONS related to this article, please post them on the public forums.

    I hope you enjoyed this one, and will also read part two and three.