[ Team LiB ] Previous Section Next Section

Testing Classes and Objects

We have already seen how we can use functions like gettype(), is_int(), and so on to test data types. This process is very useful in ensuring that functions are supplied with the right arguments.

The Reflection API

graphics/bytheway_icon.gif

If you want to examine your script's objects, methods, and properties in fine detail at runtime, you should look at another feature new to PHP 5. Discussing the Reflection API is beyond the scope of this book, but by the time you read this, documentation for it should be available in the manual at http://www.php.net/manual.

The Reflection API is a set of built-in classes with methods for discovering everything you might need to know about an object's class given an instance of the object. Typical uses for this tool include automatic documentation and dynamic mechanisms for querying objects and saving their data to relational databases.


All objects belong to the "object" data type, but we sometimes need more information than that.

Finding the Class of an Object

We have already seen that we can use hints with PHP 5 to ensure that we are working with an object belonging to a particular type. Sometimes, you might still want to confirm the type of an object. You can query the type of any object with the get_class() function. get_class() accepts an object and returns the name of its class (in lowercase letters). So given an array of objects, you might want to test each one before working with it:


foreach ( $objectArray as $obj ) {
  if ( get_class( $obj ) == "priceitem" ) {
    print "doing a pricey thing\n";
  } else {
    die ("not designed to handle ".get_class( $obj ) );
  }
}

get_class() will only tell us that an object belongs to a certain class. This information is of limited use. We generally need to know the type of an object rather than its class. In the preceding fragment, a subclass of PriceItem would fail the get_class() test. This is probably not what we want because objects from PriceItem subclasses are guaranteed to support the same interface as those instantiated from PriceItem itself.

Finding the Family of an Object

In PHP 4, the is_a() function provides us with the best tool for determining type. is_a() accepts an object and the name of the class from which the object should be derived. If the object's class is the same as, or a subclass of, the class argument provided, the function returns true; otherwise, it returns false.

So if you are not running PHP 5, or if you have written PHP 4 compatible code, you can test a method to an argument using is_a():


function addItem( $item ) {
  if ( ! is_a( $item, "item" ) ) {
    die( "required a item object" );
  }
  array_push ( $this->items, $item );
}

When testing object types in PHP 5, you should use the new instanceof keyword. instanceof provides the same information as the is_a() function, but it uses operator rather than function syntax. You can see it in action in the following fragment:


if (! $item instanceof item) {
  //...
}

The object to be tested is the left operand, and the class name to test the object against is the right operand. The entire expression reads like a sentence: "$item is an instance of item".

Checking for Class and Method Existence

As libraries grow, classes become increasingly interdependent. With this interdependence comes the possibility that a class might attempt to invoke another that is not available to the script. PHP provides you with functions for testing both class and method existence.

class_exists() requires a string representing a class name. If the user-defined class is found, the function returns true. Otherwise, it returns false. class_exists() is especially useful when using class names stored in strings:


if ( class_exists( $class_name ) ) {
  $obj = new $class_name( );
}

method_exists() requires two arguments, an object and a string containing the name of the method you are checking for:


if ( method_exists( $filter_object, "filter") ) {
  print $filter_object->filter( "hello you<br />" );
}



    [ Team LiB ] Previous Section Next Section