Advanced OOP Features For Codewalkers (ALREADY USED)

Beginning PHP and PostgreSQL 8:  From Novice to Professional 

Written by W. Jason Gilmore, Robert H. Treat

Note – fix empty spaces

Published by Apress

Chapter 7



Chapter 6 introduced the fundamentals of object-oriented PHP programming. This chapter builds on that foundation by introducing several of the more advanced OOP features that you should consider once you have mastered the basics. Specifically, this chapter introduces the following five features:

  1. Object cloning: One of the major improvements to PHP’s OOP model in version 5 is the treatment of all objects as references rather than values. However, how do you go about creating a copy of an object if all objects are treated as references? By cloning the object, a feature that is new in PHP 5. 
     
  2. Inheritance: As mentioned in Chapter 6, the ability to build class hierarchies through inheritance is a key concept of OOP. This chapter introduces PHP 5’s inheritance features and syntax, and includes several examples that demonstrate this key OOP feature. 
     
  3. Interfaces: An interface is a collection of unimplemented method definitions and constants that serves as a class blueprint of sorts. Interfaces define exactly what can be done with the class, without getting bogged down in implementation-specific details. This chapter introduces PHP 5’s interface support and offers several examples demonstrating this powerful OOP feature. 
     
  4. Abstract classes: An abstract class is essentially a class that cannot be instantiated. Abstract classes are intended to be inherited by a class that can be instantiated, better known as a concrete class. Abstract classes can be fully implemented, partially implemented, or not implemented at all. This chapter presents general concepts surrounding abstract classes, coupled with an introduction to PHP 5’s class abstraction capabilities. 
     
  5. Reflection: As you learned in Chapter 6, hiding the application’s gruesome details behind a friendly interface (encapsulation) is one of the main OOP tenants. However, programmers nonetheless require a convenient means for investigating a class’s behavior. A concept known as reflection provides that capability, as described in this chapter.

Advanced OOP Features Not Supported by PHP

If you have experience in other object-oriented languages, you might be scratching your head over why the previous list of features doesn’t include one or more particular OOP features that you are familiar with from other languages. The reason might well be that PHP doesn’t support those features. To save you from further head scratching, the following list enumerates the advanced OOP features that are not supported by PHP and thus are not covered in this chapter:

  1. Namespaces: Although originally planned as a PHP 5 feature, inclusion of namespace support was soon removed. It isn’t clear whether namespace support will be integrated into a future version. 
     
  2. Method overloading: The ability to implement polymorphism through functional overloading is not supported by PHP and, according to a discussion on the Zend Web site, probably never will be. Learn more about why at http://www.zend.com/php/ ask_experts.php
     
  3. Operator overloading: The ability to assign additional meanings to operators based upon the type of data you’re attempting to modify did not make the cut this time around. According to the aforementioned Zend Web site discussion, it is unlikely that this feature will ever be implemented. 
     
  4. Multiple inheritance: PHP does not support multiple inheritance. Implementation of multiple interfaces is supported, however.

Only time will tell whether any or all of these features will be supported in future versions of PHP.

Object Cloning

One of the biggest drawbacks to PHP 4’s object-oriented capabilities was its treatment of objects as just another data type, which impeded the use of many common OOP methodologies, such as the use of design patterns. Such methodologies depend on the ability to pass objects to other class methods as references, rather than as values, which was PHP’s default practice. Thankfully, this matter has been resolved with PHP 5, and now all objects are treated by default as references. However, because all objects are treated as references rather than as values, it is now more difficult to copy an object. If you try to copy a referenced object, it will simply point back to the addressing location of the original object. To remedy the problems with copying, PHP offers an explicit means for cloning an object.

Cloning Example

You clone an object by prefacing it with the clone keyword, like so:

destinationobject = clone targetobject;

Listing 7-1 offers a comprehensive object-cloning example. This example uses a sample class named corporatedrone , which contains two members ( employeeid and tiecolor ) and corresponding getters and setters for these members. The example code instantiates a corporatedrone object and uses it as the basis for demonstrating the effects of a clone operation.

Listing 7-1. Cloning an Object with the clone Keyword

<?php
   class corporatedrone {
      private $employeeid;
      private $tiecolor;

      // Define a setter and getter for $employeeid
      function setEmployeeID($employeeid) {
         $this->employeeid = $employeeid;
      }
      function getEmployeeID() {
         return $this->employeeid;
      }

      // Define a setter and getter for $tiecolor
      function setTiecolor($tiecolor) {
         $this->tiecolor = $tiecolor;
      }
      function getTiecolor() {
         return $this->tiecolor;
      }
   }
   // Create new corporatedrone object
   $drone1 = new corporatedrone();

   // Set the $drone1 employeeid member
   $drone1->setEmployeeID("12345");

   // Set the $drone1 tiecolor member
   $drone1->setTiecolor("red");

   // Clone the $drone1 object
   $drone2 = clone $drone1;

   // Set the $drone2 employeeid member
   $drone2->setEmployeeID("67890");

   // Output the $drone1 and $drone2 employeeid members
   echo "drone1 employeeID: ".$drone1->getEmployeeID()."<br />";
   echo "drone1 tie color: ".$drone1->getTiecolor()."<br />";
   echo "drone2 employeeID: ".$drone2->getEmployeeID()."<br />";
   echo "drone2 tie color: ".$drone2->getTiecolor()."<br />";
?>

Executing this code returns the following output:

——————————————–
drone1 employeeID: 12345
drone1 tie color: red
drone2 employeeID: 67890
drone2 tie color: red
——————————————–

As you can see, $drone2 became an object of type corporatedrone and inherited the member values of $drone1 . To further demonstrate that $drone2 is indeed of type corporatedrone , its employeeid member was also reassigned.

The __clone() Method

You can tweak an object’s cloning behavior by defining a __clone() method within the object class. Any code in this method will execute during the cloning operation. This occurs in addition to the copying of all existing object members to the target object. Now the corporatedrone class is revised, adding the following method:  

function __clone() {
  
$this->tiecolor = "blue";
}

With this in place, let’s create a new corporatedrone object, add the employeeid member value, clone it, and then output some data to show that the cloned object’s tiecolor was indeed set through the __clone() method. Listing 7-2 offers the example.

Listing 7-2. Extending clone’s Capabilities with the __clone() Method

  // Create new corporatedrone object
  $drone1 = new corporatedrone();

  // Set the $drone1 employeeid member
  $drone1->setEmployeeID("12345");

  // Clone the $drone1 object
 
$drone2 = clone $drone1;

  // Set the $drone2 employeeid member
  $drone2->setEmployeeID("67890");

  // Output the $drone1 and $drone2 employeeid members
  echo "drone1 employeeID: ".$drone1->getEmployeeID()."<br />";
 
echo "drone2 employeeID: ".$drone2->getEmployeeID()."<br />";
  echo "drone2 tiecolor: ".$drone2->getTiecolor()."<br />";

Executing this code returns the following output:

——————————————
drone1 employeeID: 12345
drone2 employeeID: 67890
drone2 tiecolor: blue
——————————————–

Inheritance

People are quite adept at thinking in terms of organizational hierarchies; thus, it doesn’t come as a surprise that we make widespread use of this conceptual view to manage many aspects of our everyday lives. Corporate management structures, the United States tax system, and our view of the plant and animal kingdoms are just a few examples of systems that rely heavily on hierarchical concepts. Because object-oriented programming is based on the premise of allowing us humans to closely model the properties and behaviors of the real-world environment we’re trying to implement in code, it makes sense to also be able to represent these hierarchical relationships.

For example, suppose that your application calls for a class titled employee , which is intended to represent the characteristics and behaviors that one might expect from an employee. Some class members that represent characteristics might include:

  1. name : The employee’s name
  2. age : The employee’s age 
     
  3. salary : The employee’s salary
  4. years_employed : The number of years the employee has been with the company 

    Some employee class methods might include:
  5. doWork : Perform some work-related task 
     
  6. eatLunch : Take a lunch break 
     
  7. takeVacation : Make the most of those valuable two weeks

These characteristics and behaviors would be relevant to all types of employees, regardless of the employee’s purpose or stature within the organization. Obviously, though, there are also differences among employees; for example, the executive might hold stock options and be able to pillage the company, while other employees are not afforded such luxuries. An assistant must be able to take a memo, and an office manager needs to take supply inventories. Despite these differences, it would be quite inefficient if you had to create and maintain redundant class structures for those attributes that all classes share. The OOP development paradigm takes this into account, allowing you to inherit from and build upon existing classes.

Class Inheritance

As applied to PHP, class inheritance is accomplished by using the extends keyword. Listing 7-3 demonstrates this ability, first creating an Employee class, and then creating an Executive class that inherits from Employee .


Note  A class that inherits from another class is known as a child class, or a subclass. The class from which the child class inherits is known as the parent, or base class.


Listing 7-3. Inheriting from a Base Class

<?php
  
# Define a base Employee class
   class Employee {

      private $name;

      # Define a setter for the private $name member.
     
function setName($name) {
         if ($name == "") echo "Name cannot be blank!";
         else $this->name = $name;
     
}

      # Define a getter for the private $name member
      function getName() {
         return "My name is ".$this->name."<br />";
      }
   } #end Employee class

   # Define an Executive class that inherits from Employee
  
class Executive extends Employee {
      # Define a method unique to Employee
      function pillageCompany() {
        
echo "I’m selling company assets to finance my yacht!";
      }
   } #end Executive class

   # Create a new Executive object
   $exec = new Executive();

   # Call the setName() method, defined in the Employee class
   $exec->setName("Richard");

   # Call the getName() method
   echo $exec->getName();

   # Call the pillageCompany() method
   $exec->pillageCompany();
?>

This returns the following:

——————————————–
My name is Richard.
I’m selling company assets to finance my yacht!
——————————————–

Because all employees have a name, the Executive class inherits from the Employee class, saving you the hassle of having to re-create the name member and the corresponding getter and setter. You can then focus solely on those characteristics that are specific to an executive, in this case a method named pillageCompany() . This method is available solely to objects of type Executive , and not to the Employee class or any other class, unless of course we create a class that inherits from Executive . The following example demonstrates that concept, producing a class titled CEO , which inherits from Executive :

<?php 

   class Employee {
   …
   }

   class Executive extends Employee {
   …
   }

   class CEO extends Executive {
      function getFacelift() {
         echo "nip nip tuck tuck";
      }
   }

   $ceo = new CEO();
   $ceo->setName("Bernie");
   $ceo->pillageCompany();
   $ceo->getFacelift();

?>

Because Executive has inherited from Employee , objects of type CEO also have all the members and methods that are available to Executive .

Inheritance and Constructors

A common question pertinent to class inheritance has to do with the use of constructors. Does a parent class constructor execute when a child is instantiated? If so, what happens if the child class also has its own constructor? Does it execute in addition to the parent constructor, or does it override the parent? Such questions are answered in this section.

If a parent class offers a constructor, it does execute when the child class is instantiated, provided that the child class does not also have a constructor. For example, suppose that the Employee class offers this constructor:

function __construct($name) {
   $this->setName($name);
}

Then you instantiate the CEO class and retrieve the name member:

$ceo = new CEO("Dennis");
echo $ceo->getName();

It will yield the following:

——————————————–
My name is Dennis
——————————————–

However, if the child class also has a constructor, that constructor will execute when the child class is instantiated, regardless of whether the parent class also has a constructor. For example, suppose that in addition to the Employee class containing the previously described constructor, the CEO class contains this constructor:

  function __construct() {
     echo "<p>CEO 
object created!</p>";
 
}

Then you instantiate the CEO class:

$ceo = new CEO("Dennis");
echo $ceo->getName();

This time it will yield the following, because the CEO constructor overrides the Employee constructor:

——————————————–
CEO object created!
My name is
——————————————–

When it comes time to retrieve the name member, you find that it’s blank, because the setName() method, which executes in the Employee constructor, never fires. Of course, you’re quite likely going to want those parent constructors to also fire. Not to fear, because there is a simple solution. Modify the CEO constructor like so:

  function __construct($name) {
     parent::__construct($name);
     echo "
<p>CEO object created!</p>";
 
} 

Again instantiating the CEO class and executing getName() in the same fashion as before, this time you’ll see a different outcome:

——————————————–
CEO object created!
My name is Dennis
——————————————–

You should understand that when parent::__construct() was encountered, PHP began a search upward through the parent classes for an appropriate constructor. Because it did not find one in Executive , it continued the search up to the Employee class, at which point it located an appropriate constructor. If PHP had located a constructor in the Employee class, then it would have fired. If you want both the Employee and Executive constructors to fire, then you need to place a call to parent::__construct() in the Executive constructor.

You also have the option to reference parent constructors in another fashion. For example, suppose that both the Employee and Executive constructors should execute when a new CEO object is created. As mentioned in the last chapter, these constructors can be referenced explicitly within the CEO constructor like so:

  function __construct($name) {
    
Employee::__construct($name);
    
Executive::__construct();
    
echo " <p>CEO object created!</p>";
 
}

Interfaces

An interface defines a general specification for implementing a particular service, declaring the required functions and constants, without specifying exactly how it must be implemented. Implementation details aren’t provided because different entities might need to implement the published method definitions in different ways. The point is to establish a general set of guidelines that must be implemented in order for the interface to be considered implemented. 

Caution Class members are not defined within interfaces! This is a matter left entirely to the implementing class.

Take for example the concept of pillaging a company. This task might be accomplished in a variety of ways, depending upon who is doing the dirty work. For example, a typical employee might do his part by using the office credit card to purchase shoes and movie tickets, writing the purchases off as “office expenses,” while an executive might force his assistant to reallocate funds to his Swiss bank account through the online accounting system. Both employees are intent on accomplishing the task, but each goes about it in a different way. In this case, the goal of the interface is to define a set of guidelines for pillaging the company, and then ask the respective classes to implement that interface accordingly. For example, the interface might consist of just two methods:

emptyBankAccount()
burnDocuments()

You can then ask the Employee and Executive classes to implement these features. In this section, you’ll learn how this is accomplished. First, however, take a moment to understand how PHP 5 implements interfaces. In PHP, an interface is created like so:

interface IinterfaceName
{
  
CONST 1;
  

  
CONST N;

   function methodName1();
  

  
function methodNameN();
}


Tip It’s common practice to preface the names of interfaces with the letter I to make them easier to recognize.


The contract is completed when a class implements the interface, via the implements keyword. All methods must be implemented, or the implementing class must be declared abstract (a concept introduced in the next section), or else a fatal error similar to the following will occur:

Fatal error: Class Executive contains 1 abstract methods and must
therefore be declared abstract (pillageCompany::emptyBankAccount) in
/www/htdocs/pmnp/7/executive.php on line 30

The following is the general syntax for implementing the preceding interface:

class className implements interfaceName
{
   
function methodName1()
   
{
      
/* methodName1() implementation */
    }
    ….
   
function methodNameN()
    {
       /* methodName1() implementation */
    }
}

Implementing a Single Interface

This section presents a working example of PHP’s interface implementation by creating and implementing an interface, named IPillage, that is used to pillage the company:

interface IPillage
{
   function emptyBankAccount();
   function burnDocuments();
}

This interface is then implemented for use by the Executive class:

class Executive extends Employee implements IPillage
{
   private $totalStockOptions;

   function emptyBankAccount()
   {
      echo "Call CFO and ask to transfer funds to Swiss bank account.";
   }

   function burnDocuments()
   {
      echo "Torch the office suite.";
   }
}

Because pillaging should be carried out at all levels of the company, we can implement the same interface by the Assistant class:

class Assistant extends Employee implements IPillage
{
   function takeMemo() {
      echo "Taking memo…";
   }

   function emptyBankAccount()
   {
      echo "Go on shopping spree with office credit card.";
   }
   function burnDocuments()
   {
      echo "Start small fire in the trash can.";
   }
}

As you can see, interfaces are particularly useful because, although they define the number and name of the methods required for some behavior to occur, they acknowledge the fact that different classes might require different ways of carrying out those methods. In this example, the Assistant class burns documents by setting them on fire in a trash can, while the Executive class does so through somewhat more aggressive means (setting his office on fire).

Implementing Multiple Interfaces

Of course, it wouldn’t be fair if we allowed outside contractors to pillage the company; after all, it was upon the backs of our full-time employees that the organization was built. That said, how can we provide our employees with the ability to both do their job and pillage the company, while limiting contractors solely to the tasks required of them? The solution is to break these tasks down into several tasks and then implement multiple interfaces as necessary. Such a feature is available to PHP 5. Consider this example:

<?php
  
interface IEmployee {…}
  
interface IDeveloper {…}
  
interface IPillage {…}

   class Employee implements IEmployee, IDeveloper, iPillage {
   …
   }

   class Contractor implements IEmployee, IDeveloper {
   …
 
  
}

?>

As you can see, all three interfaces ( IEmployee , IDeveloper , and IPillage ) have been made available to the employee, while only IEmployee and IDeveloper have been made available to the contractor.

Abstract Classes

An abstract class is a class that really isn’t supposed to ever be instantiated, but instead serves as a base class to be inherited by other classes. For example, consider a class titled Media, intended to embody the common characteristics of various types of published materials, such as newspapers, books, and CDs. Because the Media class doesn’t represent a real-life entity, but is instead a generalized representation of a range of similar entities, you’d never want to instantiate it directly. To ensure that this doesn’t happen, the class is deemed abstract. The various derived Media classes then inherit this abstract class, ensuring conformity among the child classes, because all methods defined in that abstract class must be implemented within the subclass.

A class is declared abstract by prefacing the definition with the word abstract , like so:

abstract class classname
{
       // insert attribute definitions here
       // insert method definitions here
}

Attempting to instantiate an abstract class results in the following error message:

Fatal error: Cannot instantiate abstract class staff in
/www/book/chapter06/class.inc.php.

Abstract classes ensure conformity because any classes derived from them must implement all abstract methods derived within the class. Attempting to forego implementation of any abstract method defined in the class results in a fatal error.


ABSTRACT CLASS OR INTERFACE?

When should you use an interface instead of an abstract class, and vice versa? This can be quite confusing and is often a matter of considerable debate. However, there are a few factors that can help you formulate a decision in this regard:

  • If you intend to create a model that will be assumed by a number of closely related obects, use an abstract class. If you intend to create functionality that will subsequently be embraced by a number of unrelated objects, use an interface.
  • If your object must inherit behavior from a number of sources, use an interface. PHP classes can inherit multiple interfaces but cannot extend multiple abstract classes.
  • If you know that all classes will share a common behavior implementation, use an abstract class and implement the behavior there. You cannot implement behavior in an interface.

Reflection

The classes used as examples in this and the previous chapters were for demonstrational purposes only, and therefore were simplistic enough that most of the features and behaviors could be examined at a single glance. However, real-world applications often require much more complex code. For instance, it isn’t uncommon for a single application to consist of dozens of classes, with each class consisting of numerous members and complex methods. While opening the code in an editor does facilitate review, what if you just want to retrieve a list of all available classes, or all class methods or members for a specific class? Or perhaps you’d like to know the scope of a particular method (abstract, private, protected, public, or static). Sifting through the code to make such determinations can quickly grow tedious.

The idea of inspecting an object to learn more about it is known as introspection, whereas the process of actually doing so is called reflection. As of version 5, PHP offers a reflection API that is capable of querying not only classes and methods, but also functions, interfaces, and extensions. This section introduces reflection as applied to the review of classes and methods.


Tip The PHP manual offers more about the other features available to PHP’s reflection API. See http://www.php.net/oop5.reflection for more information.


As related to class and method introspection, the PHP reflection API consists of four classes: ReflectionClass , ReflectionMethod , ReflectionParameter , and ReflectionProperty . Each class is introduced in turn in the following sections.

Writing the ReflectionClass Class

The ReflectionClass class is used to learn all about a class. It is capable of determining whether the class is a child class of some particular parent, retrieving a list of class methods and members, verifying whether the class is final, and much more. Listing 7-4 presents the ReflectionClass class contents. Although it isn’t practical to introduce each of the more than 30 methods available to this class, the method names are fairly self-explanatory regarding their purpose. An example follows the listing.

Listing 7-4. The ReflectionClass Class

class ReflectionClass implements Reflector
{
   final private __clone()
   public object __construct(string name) 
   public string __toString()

   public static string export()

   public mixed getConstant(string name)
   public array getConstants()
   public ReflectionMethod getConstructor()
   public array getDefaultProperties()
   public string getDocComment()
   public int getEndLine()
   public string getExtensionName()
   public string getFileName()
   public ReflectionClass[] getInterfaces()
   public ReflectionMethod[] getMethods()
   public ReflectionMethod getMethod(string name)
  
public int getModifiers()
   public string getName()
   public ReflectionClass getParentClass()
   public ReflectionProperty[] getProperties()
   public ReflectionProperty getProperty(string name)
   public int getStartLine()
   public array getStaticProperties()

   # The following three methods were introduced in PHP 5.1

   public bool hasConstant(string name)
   public bool hasMethod(string name)
   public bool hasProperty(string name)

   public bool implementsInterface(string name)

   public bool isAbstract()
   public bool isFinal()
   public bool isInstance(stdclass object)
   public bool isInstantiable()
   public bool isInterface()
   public bool isInternal()
   public bool isSubclassOf(ReflectionClass class)
   public bool isIterateable()
   public bool isUserDefined()

   public stdclass newInstance(mixed* args)

   public ReflectionExtension getExtension()

}

To see ReflectionClass in action, let’s use it to examine the corporatedrone class first created in Listing 7-1:

<?php

   $class = new ReflectionClass("corporatedrone");

   # Retrieve and output class methods
   $methods = $class->getMethods();

   echo "Class methods: <br />";

   foreach($methods as $method)
      echo $method->getName()."<br />";

   # Is the class abstract or final?
   $isAbstract = $class->isAbstract() ? "Yes" : "No";
   $isFinal = $class->isFinal() ? "Yes" : "No";

   echo "<br />";
   echo "Is class ".$class->getName()." Abstract: ".$isAbstract."<br />";
   echo "Is class ".$class->getName()." Final: ".$isFinal."<br />";

?>

Executing this example returns the following output:

——————————————–
Class methods:
setEmployeeID
getEmployeeID
setTiecolor
getTiecolor

Is class corporatedrone Abstract: No
Is class corporatedrone Final: No
——————————————–

Writing the ReflectionMethod Class

The ReflectionMethod class is used to learn more about a particular class method. Listing 7-5 presents the ReflectionMethod class contents. An example following the listing illustrates some of this class’s capabilities.

Listing 7-5. The ReflectionMethod Class

class ReflectionMethod extends ReflectionFunction
{
  
public __construct(mixed class, string name)
  
public string __toString()

   public static string export()

   public int getModifiers()
   public ReflectionClass getDeclaringClass()

   public mixed invoke(stdclass object, mixed* args)
   public mixed invokeArgs(stdclass object, array args)

   public bool isAbstract()
   public bool isConstructor()
  
public bool isDestructor()
  
public bool isFinal()
   public bool isPrivate()
   public bool isProtected()
   public bool isPublic()
   public bool isStatic()

   # ReflectionMethod inherits from ReflectionFunction
   # (not covered in this book), therefore the following methods
   # are made available to it.

   final private __clone()

   public string getName()

   public bool isInternal()
   public bool isUserDefined()

   public string getDocComment()
   public int getEndLine()
   public string getFileName()
   public int getNumberOfRequiredParameters()
   public int getNumberOfParameters()
   public ReflectionParameter[] getParameters()
   public int getStartLine()
   public array getStaticVariables()

   public bool returnsReference()

}

Let’s use the ReflectionMethod class to learn more about the setTieColor() method defined in the corporatedrone class (see Listing 7-1):

<?php
  
$method = new ReflectionMethod("corporatedrone", "setTieColor"); 

   $isPublic = $method->isPublic() ? "Yes" : "No";

   printf ("Is %s public: %s <br />", $method->getName(), $isPublic);

   printf ("Total number of parameters: %d", $method->getNumberofParameters());
?>

Executing this example produces this output:

——————————————–
Is setTiecolor public: Yes
Total number of parameters: 1

——————————————–

Writing the ReflectionParameter Class

The ReflectionParameter class is used to learn more about a method’s parameters. Listing 7-6 presents the ReflectionParameter class contents. An example following the listing demonstrates some of this class’s capabilities.

Listing 7-6. The ReflectionParameter Class

class ReflectionParameter implements Reflector
{
   final private __clone()
   public object __construct(string name)
   public string __toString()

   public bool allowsNull()

   public static string export()

   public ReflectionClass getClass()
   public mixed getDefaultValue() # introduced in PHP 5.1.0
   public string getName()

   public bool isDefaultValueAvailable() # introduced in PHP 5.1.0
   public bool isOptional() # introduced in PHP 5.1.0
   public bool isPassedByReference()

}

Let’s use the ReflectionParameter class to learn more about the setTieColor() method’s input parameters (this method is found in the corporatedrone class in Listing 7-1):

<?php
  
$method = new ReflectionMethod("corporatedrone", "setTieColor");
   $parameters = $method->getParameters();
   foreach ($parameters as $parameter) echo $parameter->getName()."<br />";
?>

Executing this example returns the following:

——————————————–
tiecolor
——————————————–


Note  It’s presently not possible to learn more about a specific method or function parameter. The only way to do so is to loop through all of them, as is done in the preceding example. Of course, it would be fairly easy to extend this class to offer such a feature.


Writing the ReflectionProperty Class

The ReflectionProperty class is used to learn more about a particular class’s properties. Listing 7-7 presents the ReflectionProperty class contents. An example demonstrating this class’s capabilities follows the listing.

Listing 7-7. The ReflectionProperty Class

class ReflectionProperty implements Reflector
{
   final private __clone()
   public __construct(mixed class, string name)
   public string __toString()

   public static string export()

   public ReflectionClass getDeclaringClass()
   public string getDocComment() # introduced in PHP 5.1.0
   public int getModifiers()
   public string getName()
   public mixed getValue(stdclass object)

   public bool isPublic()
   public bool isPrivate()
   public bool isProtected()
   public bool isStatic()
   public bool isDefault()

   public void setValue(stdclass object, mixed value)

}

Let’s use the ReflectionProperty class to learn more about the corporatedrone class’s properties (the corporatedrone class is found in Listing 7-1):

<?php
  
$method = new ReflectionClass("corporatedrone"); 

   $properties = $method->getProperties();

   foreach ($properties as $property) echo $property->getName()."<br />";
?>

This example returns the following output:

——————————————–
employeeid
tiecolor
——————————————–

Other Reflection Applications

While reflection is useful for purposes such as those described in the preceding sections, you may be surprised to know that it can also be applied to a variety of tasks, including testing code, generating documentation, and performing other duties. For instance, the following two PEAR packages depend upon the reflection API to carry out their respective tasks: 

  1. PHPDoc : Useful for automatically generating code documentation based on comments embedded in the source code (see http://www.pear.php.net/package/PHPDoc )
  2. PHPUnit2 : A testing framework for performing unit tests (see http://www.pear.php.net/package/PHPUnit2 )

Consider examining the contents of these packages to learn about the powerful ways in which they harness reflection to carry out useful tasks.

Summary

This and the previous chapter introduced you to the entire gamut of PHP’s OOP features, both old and new. Although the PHP development team was careful to ensure that users aren’t constrained to use these features, the improvements and additions made regarding PHP’s ability to operate in conjunction with this important development paradigm represent a quantum leap forward for the language. If you’re an old hand at object-oriented programming, hopefully these last two chapters have left you smiling ear-to-ear over the long-awaited capabilities introduced within these pages. If you’re new to OOP, the material should help you to better understand many of the key OOP concepts and inspire you to perform additional experimentation and research.

The next chapter introduces yet another new, and certainly long-awaited, feature of PHP 5: exception handling.

 

 

 

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye