Object-Oriented PHP for Beginners

Object-Oriented PHP for Beginners

Tutorial Details
  • Program : PHP
  • Version (if applicable) : PHP 5+
  • Difficulty: Intermediate
  • Estimated Completion Time: 2 Hours
Share

“For added control over objects, methods and properties are assigned visibility.”

Note — Visibility is a new feature as of PHP 5. For information on OOP compatibility with PHP 4 , see the PHP manual page.

Public Properties and Methods

All the methods and properties you’ve used so far have been public. This means that they can be accessed anywhere, both within the class and externally.

Protected Properties and Methods

When a property or method is declared protected , it can only be accessed within the class itself or in descendant classes (classes that extend the class containing the protected method).

Declare the getProperty() method as protected in MyClass and try to access it directly from outside the class:

  1. <?php  
  2.   
  3. class  MyClass  
  4. {  
  5.     public   $prop1  =  "I'm a class property!" ;  
  6.   
  7.     public   function  __construct()  
  8.     {  
  9.         echo  'The  class   "', __CLASS__, '"  was initiated!<br /> ';  
  10.     }  
  11.  
  12.     public function __destruct()  
  13.     {  
  14.         echo ' The  class   "', __CLASS__, '"  was destroyed.<br />';  
  15.     }  
  16.   
  17.     public   function  __toString()  
  18.     {  
  19.         echo   "Using the toString method: " ;  
  20.         return   $this ->getProperty();  
  21.     }  
  22.   
  23.     public   function  setProperty( $newval )  
  24.     {  
  25.         $this ->prop1 =  $newval ;  
  26.     }  
  27.   
  28.     protected   function  getProperty()  
  29.     {  
  30.         return   $this ->prop1 .  "<br />" ;  
  31.     }  
  32. }  
  33.   
  34. class  MyOtherClass  extends  MyClass  
  35. {  
  36.     public   function  __construct()  
  37.     {  
  38.         parent::__construct();  
  39.         echo   "A new constructor in "  .  __CLASS__  .  ".<br />" ;  
  40.     }  
  41.   
  42.     public   function  newMethod()  
  43.     {  
  44.         echo   "From a new method in "  .  __CLASS__  .  ".<br />" ;  
  45.     }  
  46. }  
  47.   
  48. // Create a new object   
  49. $newobj  =  new  MyOtherClass;  
  50.   
  51. // Attempt to call a protected method   
  52. echo   $newobj ->getProperty();  
  53.   
  54. ?>  
<?php

class MyClass
{
    public $prop1 = "I'm a class property!";

    public function __construct()
    {
        echo 'The class "', __CLASS__, '" was initiated!<br />';
    }

    public function __destruct()
    {
        echo 'The class "', __CLASS__, '" was destroyed.<br />';
    }

    public function __toString()
    {
        echo "Using the toString method: ";
        return $this->getProperty();
    }

    public function setProperty($newval)
    {
        $this->prop1 = $newval;
    }

    protected function getProperty()
    {
        return $this->prop1 . "<br />";
    }
}

class MyOtherClass extends MyClass
{
    public function __construct()
    {
        parent::__construct();
		echo "A new constructor in " . __CLASS__ . ".<br />";
    }

    public function newMethod()
    {
        echo "From a new method in " . __CLASS__ . ".<br />";
    }
}

// Create a new object
$newobj = new MyOtherClass;

// Attempt to call a protected method
echo $newobj->getProperty();

?>

Upon attempting to run this script, the following error shows up:

  1. The  class   "MyClass"  was initiated!  
  2. new  constructor in MyOtherClass.  
  3.   
  4. Fatal error: Call to protected  method MyClass::getProperty() from context  ''  in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 55  
The class "MyClass" was initiated!
A new constructor in MyOtherClass.

Fatal error: Call to protected method MyClass::getProperty() from context '' in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 55

Now, create a new method in MyOtherClass to call the getProperty() method:

  1. <?php  
  2.   
  3. class  MyClass  
  4. {  
  5.     public   $prop1  =  "I'm a class property!" ;  
  6.   
  7.     public   function  __construct()  
  8.     {  
  9.         echo  'The  class   "', __CLASS__, '"  was initiated!<br /> ';  
  10.     }  
  11.  
  12.     public function __destruct()  
  13.     {  
  14.         echo ' The  class   "', __CLASS__, '"  was destroyed.<br />';  
  15.     }  
  16.   
  17.     public   function  __toString()  
  18.     {  
  19.         echo   "Using the toString method: " ;  
  20.         return   $this ->getProperty();  
  21.     }  
  22.   
  23.     public   function  setProperty( $newval )  
  24.     {  
  25.         $this ->prop1 =  $newval ;  
  26.     }  
  27.   
  28.     protected   function  getProperty()  
  29.     {  
  30.         return   $this ->prop1 .  "<br />" ;  
  31.     }  
  32. }  
  33.   
  34. class  MyOtherClass  extends  MyClass  
  35. {  
  36.     public   function  __construct()  
  37.     {  
  38.         parent::__construct();  
  39.         echo   "A new constructor in "  .  __CLASS__  .  ".<br />" ;  
  40.     }  
  41.   
  42.     public   function  newMethod()  
  43.     {  
  44.         echo   "From a new method in "  .  __CLASS__  .  ".<br />" ;  
  45.     }  
  46.   
  47.     public   function  callProtected()  
  48.     {  
  49.         return   $this ->getProperty();  
  50.     }  
  51. }  
  52.   
  53. // Create a new object   
  54. $newobj  =  new  MyOtherClass;  
  55.   
  56. // Call the protected method from within a public method   
  57. echo   $newobj ->callProtected();  
  58.   
  59. ?>  
<?php

class MyClass
{
    public $prop1 = "I'm a class property!";

    public function __construct()
    {
        echo 'The class "', __CLASS__, '" was initiated!<br />';
    }

    public function __destruct()
    {
        echo 'The class "', __CLASS__, '" was destroyed.<br />';
    }

    public function __toString()
    {
        echo "Using the toString method: ";
        return $this->getProperty();
    }

    public function setProperty($newval)
    {
        $this->prop1 = $newval;
    }

    protected function getProperty()
    {
        return $this->prop1 . "<br />";
    }
}

class MyOtherClass extends MyClass
{
    public function __construct()
    {
        parent::__construct();
		echo "A new constructor in " . __CLASS__ . ".<br />";
    }

    public function newMethod()
    {
        echo "From a new method in " . __CLASS__ . ".<br />";
    }

    public function callProtected()
    {
        return $this->getProperty();
    }
}

// Create a new object
$newobj = new MyOtherClass;

// Call the protected method from within a public method
echo $newobj->callProtected();

?>

This generates the desired result:

  1. The  class   "MyClass"  was initiated!  
  2. new  constructor in MyOtherClass.  
  3. I'm a class  property!  
  4. The class   "MyClass"  was destroyed.  
The class "MyClass" was initiated!
A new constructor in MyOtherClass.
I'm a class property!
The class "MyClass" was destroyed.

Private Properties and Methods

A property or method declared private is accessible only from within the class that defines it . This means that even if a new class extends the class that defines a private property, that property or method will not be available at all within the child class.

To demonstrate this, declare getProperty() as private in MyClass , and attempt to call callProtected() from
MyOtherClass :

  1. <?php  
  2.   
  3. class  MyClass  
  4. {  
  5.     public   $prop1  =  "I'm a class property!" ;  
  6.   
  7.     public   function  __construct()  
  8.     {  
  9.         echo  'The  class   "', __CLASS__, '"  was initiated!<br /> ';  
  10.     }  
  11.  
  12.     public function __destruct()  
  13.     {  
  14.         echo ' The  class   "', __CLASS__, '"  was destroyed.<br />';  
  15.     }  
  16.   
  17.     public   function  __toString()  
  18.     {  
  19.         echo   "Using the toString method: " ;  
  20.         return   $this ->getProperty();  
  21.     }  
  22.   
  23.     public   function  setProperty( $newval )  
  24.     {  
  25.         $this ->prop1 =  $newval ;  
  26.     }  
  27.   
  28.     private   function  getProperty()  
  29.     {  
  30.         return   $this ->prop1 .  "<br />" ;  
  31.     }  
  32. }  
  33.   
  34. class  MyOtherClass  extends  MyClass  
  35. {  
  36.     public   function  __construct()  
  37.     {  
  38.         parent::__construct();  
  39.         echo   "A new constructor in "  .  __CLASS__  .  ".<br />" ;  
  40.     }  
  41.   
  42.     public   function  newMethod()  
  43.     {  
  44.         echo   "From a new method in "  .  __CLASS__  .  ".<br />" ;  
  45.     }  
  46.   
  47.     public   function  callProtected()  
  48.     {  
  49.         return   $this ->getProperty();  
  50.     }  
  51. }  
  52.   
  53. // Create a new object   
  54. $newobj  =  new  MyOtherClass;  
  55.   
  56. // Use a method from the parent class   
  57. echo   $newobj ->callProtected();  
  58.   
  59. ?>  
<?php

class MyClass
{
    public $prop1 = "I'm a class property!";

    public function __construct()
    {
        echo 'The class "', __CLASS__, '" was initiated!<br />';
    }

    public function __destruct()
    {
        echo 'The class "', __CLASS__, '" was destroyed.<br />';
    }

    public function __toString()
    {
        echo "Using the toString method: ";
        return $this->getProperty();
    }

    public function setProperty($newval)
    {
        $this->prop1 = $newval;
    }

    private function getProperty()
    {
        return $this->prop1 . "<br />";
    }
}

class MyOtherClass extends MyClass
{
    public function __construct()
    {
        parent::__construct();
        echo "A new constructor in " . __CLASS__ . ".<br />";
    }

    public function newMethod()
    {
        echo "From a new method in " . __CLASS__ . ".<br />";
    }

    public function callProtected()
    {
        return $this->getProperty();
    }
}

// Create a new object
$newobj = new MyOtherClass;

// Use a method from the parent class
echo $newobj->callProtected();

?>

Reload your browser, and the following error appears:

  1. The  class   "MyClass"  was initiated!  
  2. new  constructor in MyOtherClass.  
  3.   
  4. Fatal error: Call to private  method MyClass::getProperty() from context  'MyOtherClass'  in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 49  
The class "MyClass" was initiated!
A new constructor in MyOtherClass.

Fatal error: Call to private method MyClass::getProperty() from context 'MyOtherClass' in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 49

Static Properties and Methods

A method or property declared static can be accessed without first instantiating the class; you simply supply the class name, scope resolution operator, and the property or method name.

“One of the major benefits to using static properties is that they keep their stored values for the duration of the script.”

To demonstrate this, add a static property called $count and a static method called plusOne() to MyClass . Then set up a do...while loop to output the incremented value of $count as long as the value is less than 10:

  1. <?php  
  2.   
  3. class  MyClass  
  4. {  
  5.     public   $prop1  =  "I'm a class property!" ;  
  6.   
  7.     public   static   $count  = 0;  
  8.   
  9.     public   function  __construct()  
  10.     {  
  11.         echo  'The  class   "', __CLASS__, '"  was initiated!<br /> ';  
  12.     }  
  13.  
  14.     public function __destruct()  
  15.     {  
  16.         echo ' The  class   "', __CLASS__, '"  was destroyed.<br />';  
  17.     }  
  18.   
  19.     public   function  __toString()  
  20.     {  
  21.         echo   "Using the toString method: " ;  
  22.         return   $this ->getProperty();  
  23.     }  
  24.   
  25.     public   function  setProperty( $newval )  
  26.     {  
  27.         $this ->prop1 =  $newval ;  
  28.     }  
  29.   
  30.     private   function  getProperty()  
  31.     {  
  32.         return   $this ->prop1 .  "<br />" ;  
  33.     }  
  34.   
  35.     public   static   function  plusOne()  
  36.     {  
  37.         return   "The count is "  . ++self:: $count  .  ".<br />" ;  
  38.     }  
  39. }  
  40.   
  41. class  MyOtherClass  extends  MyClass  
  42. {  
  43.     public   function  __construct()  
  44.     {  
  45.         parent::__construct();  
  46.         echo   "A new constructor in "  .  __CLASS__  .  ".<br />" ;  
  47.     }  
  48.   
  49.     public   function  newMethod()  
  50.     {  
  51.         echo   "From a new method in "  .  __CLASS__  .  ".<br />" ;  
  52.     }  
  53.   
  54.     public   function  callProtected()  
  55.     {  
  56.         return   $this ->getProperty();  
  57.     }  
  58. }  
  59.   
  60. do   
  61. {  
  62.     // Call plusOne without instantiating MyClass   
  63.     echo  MyClass::plusOne();  
  64. while  ( MyClass:: $count  < 10 );  
  65.   
  66. ?>  
<?php

class MyClass
{
    public $prop1 = "I'm a class property!";

    public static $count = 0;

    public function __construct()
    {
        echo 'The class "', __CLASS__, '" was initiated!<br />';
    }

    public function __destruct()
    {
        echo 'The class "', __CLASS__, '" was destroyed.<br />';
    }

    public function __toString()
    {
        echo "Using the toString method: ";
        return $this->getProperty();
    }

    public function setProperty($newval)
    {
        $this->prop1 = $newval;
    }

    private function getProperty()
    {
        return $this->prop1 . "<br />";
    }

    public static function plusOne()
    {
        return "The count is " . ++self::$count . ".<br />";
    }
}

class MyOtherClass extends MyClass
{
    public function __construct()
    {
        parent::__construct();
        echo "A new constructor in " . __CLASS__ . ".<br />";
    }

    public function newMethod()
    {
        echo "From a new method in " . __CLASS__ . ".<br />";
    }

    public function callProtected()
    {
        return $this->getProperty();
    }
}

do
{
    // Call plusOne without instantiating MyClass
    echo MyClass::plusOne();
} while ( MyClass::$count < 10 );

?>

Note — When accessing static properties, the dollar sign
($ ) comes after the scope resolution operator.

When you load this script in your browser, the following is output:

  1. The  count  is 1.  
  2. The count  is 2.  
  3. The count  is 3.  
  4. The count  is 4.  
  5. The count  is 5.  
  6. The count  is 6.  
  7. The count  is 7.  
  8. The count  is 8.  
  9. The count  is 9.  
  10. The count  is 10.  
The count is 1.
The count is 2.
The count is 3.
The count is 4.
The count is 5.
The count is 6.
The count is 7.
The count is 8.
The count is 9.
The count is 10.

Commenting with DocBlocks

“The DocBlock commenting style is a widely
accepted method of documenting classes.”

While not an official part of OOP, the DocBlock commenting style is a widely accepted method of documenting classes. Aside from providing a standard for
developers to use when writing code, it has also been adopted by many of the most popular software development kits (SDKs), such as Eclipse and NetBeans , and will be used to generate code hints.

A DocBlock is defined by using a block comment that starts with an additional asterisk:

  1. /**  
  2.  * This is a very basic DocBlock  
  3.  */   
/**
 * This is a very basic DocBlock
 */

The real power of DocBlocks comes with the ability to use tags , which start with an at symbol (@ ) immediately followed by the tag name and the value of the tag. DocBlock tags allow developers to define authors of a file, the license for a class, the property or method information, and other useful information.

The most common tags used follow:

  • @author : The author of the current element (which might be a class, file, method, or any bit of code) are listed using this tag. Multiple author tags can be used in the same DocBlock if more than one author is credited. The format for the author name is John Doe <john.doe@email.com> .
  • @copyright : This signifies the copyright year and name of the copyright holder for the current element. The format is 2010 Copyright Holder .
  • @license : This links to the license for the current element. The format for the license information is
    http://www.example.com/path/to/license.txt License Name .
  • @var : This holds the type and description of a variable or class property. The format is type element description .
  • @param : This tag shows the type and description of a function or method parameter. The format is type $element_name element description .
  • @return : The type and description of the return value of a function or method are provided in this tag. The format is type return element description .

A sample class commented with DocBlocks might look like this:

  1. <?php  
  2.   
  3. /**  
  4.  * A simple class  
  5.  *  
  6.  * This is the long description for this class,  
  7.  * which can span as many lines as needed. It is  
  8.  * not required, whereas the short description is  
  9.  * necessary.  
  10.  *  
  11.  * It can also span multiple paragraphs if the  
  12.  * description merits that much verbiage.  
  13.  *  
  14.  * @author Jason Lengstorf <jason.lengstorf@ennuidesign.com>  
  15.  * @copyright 2010 Ennui Design  
  16.  * @license http://www.php.net/license/3_01.txt PHP License 3.01  
  17.  */   
  18. class  SimpleClass  
  19. {  
  20.     /**  
  21.      * A public variable  
  22.      *  
  23.      * @var string stores data for the class  
  24.      */   
  25.     public   $foo ;  
  26.   
  27.     /**  
  28.      * Sets $foo to a new value upon class instantiation  
  29.      *  
  30.      * @param string $val a value required for the class  
  31.      * @return void  
  32.      */   
  33.     public   function  __construct( $val )  
  34.     {  
  35.         $this ->foo =  $val ;  
  36.     }  
  37.   
  38.     /**  
  39.      * Multiplies two integers  
  40.      *  
  41.      * Accepts a pair of integers and returns the  
  42.      * product of the two.  
  43.      *  
  44.      * @param int $bat a number to be multiplied  
  45.      * @param int $baz a number to be multiplied  
  46.      * @return int the product of the two parameters  
  47.      */   
  48.     public   function  bar( $bat$baz )  
  49.     {  
  50.         return   $bat  *  $baz ;  
  51.     }  
  52. }  
  53.   
  54. ?>  
<?php

/**
 * A simple class
 *
 * This is the long description for this class,
 * which can span as many lines as needed. It is
 * not required, whereas the short description is
 * necessary.
 *
 * It can also span multiple paragraphs if the
 * description merits that much verbiage.
 *
 * @author Jason Lengstorf <jason.lengstorf@ennuidesign.com>
 * @copyright 2010 Ennui Design
 * @license http://www.php.net/license/3_01.txt PHP License 3.01
 */
class SimpleClass
{
    /**
     * A public variable
     *
     * @var string stores data for the class
     */
    public $foo;

    /**
     * Sets $foo to a new value upon class instantiation
     *
     * @param string $val a value required for the class
     * @return void
     */
    public function __construct($val)
    {
        $this->foo = $val;
    }

    /**
     * Multiplies two integers
     *
     * Accepts a pair of integers and returns the
     * product of the two.
     *
     * @param int $bat a number to be multiplied
     * @param int $baz a number to be multiplied
     * @return int the product of the two parameters
     */
    public function bar($bat, $baz)
    {
        return $bat * $baz;
    }
}

?>

Once you scan the preceding class, the benefits of DocBlock are apparent: everything is clearly defined so that the next developer can pick up the code and never have to wonder what a snippet of code does or what it should contain.


Comparing Object-Oriented and Procedural Code

There’s not really a right and wrong way to write code. That being said, this section outlines a strong argument for adopting an object-oriented approach in software development, especially in large applications.


Reason 1: Ease of Implementation

“While it may be daunting at first, OOP actually provides an easier approach to dealing with data.”

While it may be daunting at first, OOP actually provides an easier approach to dealing with data. Because an object can store data internally, variables don’t need to be passed from function to function to work properly.

Also, because multiple instances of the same class can exist simultaneously , dealing with large data sets is infinitely easier. For instance, imagine you have two people’s information being processed in a file. They need names, occupations, and ages.

The Procedural Approach

Here’s the procedural approach to our example:

  1. <?php  
  2.   
  3. function  changeJob( $person$newjob )  
  4. {  
  5.     $person [ 'job' ] =  $newjob// Change the person's job   
  6.     return   $person ;  
  7. }  
  8.   
  9. function  happyBirthday( $person )  
  10. {  
  11.     ++$person ['age ']; // Add 1 to the person' s age  
  12.     return   $person ;  
  13. }  
  14.   
  15. $person1  =  array (  
  16.     'name'  =>  'Tom' ,  
  17.     'job'  =>  'Button-Pusher' ,  
  18.     'age'  => 34  
  19. );  
  20.   
  21. $person2  =  array (  
  22.     'name'  =>  'John' ,  
  23.     'job'  =>  'Lever-Puller' ,  
  24.     'age'  => 41  
  25. );  
  26.   
  27. // Output the starting values for the people   
  28. echo   "<pre>Person 1: " , print_r( $person1 , TRUE),  "</pre>" ;  
  29. echo   "<pre>Person 2: " , print_r( $person2 , TRUE),  "</pre>" ;  
  30.   
  31. // Tom got a promotion and had a birthday   
  32. $person1  = changeJob( $person1'Box-Mover' );  
  33. $person1  = happyBirthday( $person1 );  
  34.   
  35. // John just had a birthday   
  36. $person2  = happyBirthday( $person2 );  
  37.   
  38. // Output the new values for the people   
  39. echo   "<pre>Person 1: " , print_r( $person1 , TRUE),  "</pre>" ;  
  40. echo   "<pre>Person 2: " , print_r( $person2 , TRUE),  "</pre>" ;  
  41.   
  42. ?>  
<?php

function changeJob($person, $newjob)
{
    $person['job'] = $newjob; // Change the person's job
    return $person;
}

function happyBirthday($person)
{
    ++$person['age']; // Add 1 to the person's age
    return $person;
}

$person1 = array(
    'name' => 'Tom',
    'job' => 'Button-Pusher',
    'age' => 34
);

$person2 = array(
    'name' => 'John',
    'job' => 'Lever-Puller',
    'age' => 41
);

// Output the starting values for the people
echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>";
echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>";

// Tom got a promotion and had a birthday
$person1 = changeJob($person1, 'Box-Mover');
$person1 = happyBirthday($person1);

// John just had a birthday
$person2 = happyBirthday($person2);

// Output the new values for the people
echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>";
echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>";

?>

When executed, the code outputs the following:

  1. Person 1: Array  
  2. (  
  3.     [name] => Tom  
  4.     [job] => Button-Pusher  
  5.     [age] => 34  
  6. )  
  7. Person 2: Array  
  8. (  
  9.     [name] => John  
  10.     [job] => Lever-Puller  
  11.     [age] => 41  
  12. )  
  13. Person 1: Array  
  14. (  
  15.     [name] => Tom  
  16.     [job] => Box-Mover  
  17.     [age] => 35  
  18. )  
  19. Person 2: Array  
  20. (  
  21.     [name] => John  
  22.     [job] => Lever-Puller  
  23.     [age] => 42  
  24. )  
Person 1: Array
(
    [name] => Tom
    [job] => Button-Pusher
    [age] => 34
)
Person 2: Array
(
    [name] => John
    [job] => Lever-Puller
    [age] => 41
)
Person 1: Array
(
    [name] => Tom
    [job] => Box-Mover
    [age] => 35
)
Person 2: Array
(
    [name] => John
    [job] => Lever-Puller
    [age] => 42
)

While this code isn’t necessarily bad, there’s a lot to keep in mind while coding. The array of the affected person’s attributes must be passed and returned from each function call , which leaves margin for error.

To clean up this example, it would be desirable to leave as few things up to the developer as possible. Only absolutely essential information for the current operation should need to be passed to the functions.

This is where OOP steps in and helps you clean things up.

The OOP Approach

Here’s the OOP approach to our example:

  1. <?php  
  2.   
  3. class  Person  
  4. {  
  5.     private   $_name ;  
  6.     private   $_job ;  
  7.     private   $_age ;  
  8.   
  9.     public   function  __construct( $name$job$age )  
  10.     {  
  11.         $this ->_name =  $name ;  
  12.         $this ->_job =  $job ;  
  13.         $this ->_age =  $age ;  
  14.     }  
  15.   
  16.     public   function  changeJob( $newjob )  
  17.     {  
  18.         $this ->_job =  $newjob ;  
  19.     }  
  20.   
  21.     public   function  happyBirthday()  
  22.     {  
  23.         ++$this ->_age;  
  24.     }  
  25. }  
  26.   
  27. // Create two new people   
  28. $person1  =  new  Person( "Tom""Button-Pusher" , 34);  
  29. $person2  =  new  Person( "John""Lever Puller" , 41);  
  30.   
  31. // Output their starting point   
  32. echo   "<pre>Person 1: " , print_r( $person1 , TRUE),  "</pre>" ;  
  33. echo   "<pre>Person 2: " , print_r( $person2 , TRUE),  "</pre>" ;  
  34.   
  35. // Give Tom a promotion and a birthday   
  36. $person1 ->changeJob( "Box-Mover" );  
  37. $person1 ->happyBirthday();  
  38.   
  39. // John just gets a year older   
  40. $person2 ->happyBirthday();  
  41.   
  42. // Output the ending values   
  43. echo   "<pre>Person 1: " , print_r( $person1 , TRUE),  "</pre>" ;  
  44. echo   "<pre>Person 2: " , print_r( $person2 , TRUE),  "</pre>" ;  
  45.   
  46. ?>  
<?php

class Person
{
    private $_name;
    private $_job;
    private $_age;

    public function __construct($name, $job, $age)
    {
        $this->_name = $name;
        $this->_job = $job;
        $this->_age = $age;
    }

    public function changeJob($newjob)
    {
        $this->_job = $newjob;
    }

    public function happyBirthday()
    {
        ++$this->_age;
    }
}

// Create two new people
$person1 = new Person("Tom", "Button-Pusher", 34);
$person2 = new Person("John", "Lever Puller", 41);

// Output their starting point
echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>";
echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>";

// Give Tom a promotion and a birthday
$person1->changeJob("Box-Mover");
$person1->happyBirthday();

// John just gets a year older
$person2->happyBirthday();

// Output the ending values
echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>";
echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>";

?>

This outputs the following in the browser:

  1. Person 1: Person Object  
  2. (  
  3.     [_name:private ] => Tom  
  4.     [_job:private ] => Button-Pusher  
  5.     [_age:private ] => 34  
  6. )  
  7.   
  8. Person 2: Person Object  
  9. (  
  10.     [_name:private ] => John  
  11.     [_job:private ] => Lever Puller  
  12.     [_age:private ] => 41  
  13. )  
  14.   
  15. Person 1: Person Object  
  16. (  
  17.     [_name:private ] => Tom  
  18.     [_job:private ] => Box-Mover  
  19.     [_age:private ] => 35  
  20. )  
  21.   
  22. Person 2: Person Object  
  23. (  
  24.     [_name:private ] => John  
  25.     [_job:private ] => Lever Puller  
  26.     [_age:private ] => 42  
  27. )  
Person 1: Person Object
(
    [_name:private] => Tom
    [_job:private] => Button-Pusher
    [_age:private] => 34
)

Person 2: Person Object
(
    [_name:private] => John
    [_job:private] => Lever Puller
    [_age:private] => 41
)

Person 1: Person Object
(
    [_name:private] => Tom
    [_job:private] => Box-Mover
    [_age:private] => 35
)

Person 2: Person Object
(
    [_name:private] => John
    [_job:private] => Lever Puller
    [_age:private] => 42
)

There’s a little bit more setup involved to make the approach object oriented, but after the class is defined, creating and modifying people is a breeze; a person’s information does not need to be passed or returned from methods, and only absolutely essential information is passed to each method.

“OOP will significantly reduce your workload if implemented properly.”

On the small scale, this difference may not seem like much, but as your applications grow in size, OOP will significantly reduce your workload if implemented properly.

TipNot everything needs to be object oriented. A quick function that handles something small in one place inside the application does not necessarily need to be wrapped in a class. Use your best judgment when deciding between object-oriented and procedural approaches.


Reason 2: Better Organization

Another benefit of OOP is how well it lends itself to being easily packaged and cataloged. Each class can generally be kept in its own separate file, and if a uniform naming convention is used, accessing the classes is extremely simple.

Assume you’ve got an application with 150 classes that are called dynamically through a controller file at the root of your application filesystem. All 150 classes follow the naming convention class.classname.inc.php and reside in the inc folder of your application.

The controller can implement PHP’s __autoload() function to dynamically pull in only the classes it needs as they are called, rather than including all 150 in the controller file just in case or coming up with some clever way of including the files in your own code:

  1. <?php  
  2.     function  __autoload( $class_name )  
  3.     {  
  4.         include_once   'inc/class.'  .  $class_name  .  '.inc.php' ;  
  5.     }  
  6. ?>  
<?php
    function __autoload($class_name)
    {
        include_once 'inc/class.' . $class_name . '.inc.php';
    }
?>

Having each class in a separate file also makes code more portable and easier to reuse in new applications without a bunch of copying and pasting.


Reason 3: Easier Maintenance

Due to the more compact nature of OOP when done correctly, changes in the code are usually much easier to spot and make than in a long spaghetti code procedural implementation.

If a particular array of information gains a new attribute, a procedural piece of software may require (in a worst-case scenario) that the new attribute be added to each function that uses the array.

An OOP application could potentially be updated as easily adding the new property and then adding the methods that deal with said property.

A lot of the benefits covered in this section are the product of OOP in combination with DRY programming practices. It is definitely possible to create easy-to-maintain procedural code that doesn’t cause nightmares, and it is equally possible to create awful object-oriented code. [Pro PHP and jQuery ] will attempt to demonstrate a combination of good coding habits in conjunction with OOP to generate clean code that’s easy to read and maintain.


Summary

At this point, you should feel comfortable with the object-oriented programming style. Learning OOP is a great way to take your programming to that next level. When implemented properly, OOP will help you produce easy-to-read, easy-to-maintain, portable code that will save you (and the developers who work with you) hours of extra work. Are you stuck on something that wasn’t covered in this article? Are you already using OOP and have some tips for beginners? Share them in the comments!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值