[ Team LiB ] Previous Section Next Section

Static Methods

It is not only properties that can be declared static. As of PHP 5, you can declare a method static:


static function doOperation() {
//...

Some classes make static the utility methods that do not depend upon member variables, to make the tool more widely available. We might supply a calcTax() method in Item, for example:


class Item {
  public static $SALES_TAX=10;
  private $name;
  public static function calcTax( $amount ) {
    return ( $amount + ( $amount/(Item::$SALES_TAX/100)) );
  }
}

The calcTax() method uses the static $SALES_TAX property to calculate a new total given a starting amount. Crucially, this method does not attempt to access any standard properties. Because static methods are called outside of object context (that is, using the class name and not an object handle), they cannot use the $this pseudo-variable to access methods or properties. Let's use the calcTax() method:


$amount = 10;
print "given a cost of $amount, the total will be";
print Item::calcTax( $amount );
// prints "given a cost of 10, the total will be 110"

The benefit of using a static method in this example was that we did not need to create or acquire an Item object to gain access to the functionality in calcTax().

Let's look at another common use for static methods and properties. In Listing 17.2, we create a Shop class. Our system design calls for a central Shop object. We want client code to be able to get an instance of this object at any time, and we want to ensure that only one Shop object is created during the life of a script execution. All objects requesting a Shop object will be guaranteed to get a reference to the same object and will therefore work with the same data as one another.

Listing 17.2 Using Static Methods and Properties to Limit Instances of a Class (PHP 5 Only)
 1: <?php
 2:
 3: class Shop {
 4:   private static $instance;
 5:   public $name="shop";
 6:
 7:   private function ___construct() {
 8:     // block attempts to instantiate
 9:   }
10:
11:   public static function getInstance() {
12:     if ( empty( self::$instance ) ) {
13:     self::$instance = new Shop();
14:     }
15:     return self::$instance;
16:   }
17: }
18:
19: // $s = new Shop();
20: // would fail because ___construct() is declared private
21:
22: $first = Shop::getInstance();
23: $first-> name="Acme Shopping Emporium";
24:
25: $second = Shop::getInstance();
26: print $second -> name;
27: // prints "Acme Shopping Emporium"
28: ?>

Listing 17.2 shows an example of a design pattern called singleton. It is intended to ensure that only one instance of a class exists in a process at any time and that any client code can easily access that instance. We declare a private static property called $instance on line 4. On line 5, we declare and assign to a property called $name. We will use it to test our class later. Notice that we declared the constructor private on line 7. This declaration makes it impossible for any external code to create an instance of the Shop object. We declare a static method called getInstance() on line 11. Because it is static, getInstance() can be called through the class rather than the object instance:


Shop::getInstance();

As a member function, getInstance() has privileged status. It can set and get the static $instance property. It can also create a new instance of the shop object using new. We test $instance and assign a Shop object to it if it is empty. After the test, we can be sure that we have a Shop object in the $instance property, and we return it to the user on line 15.

We use the self keyword to access the $instance property. self refers to the current class in the same way that $this refers to the current object.

We call getInstance() on line 25, acquiring a Shop object. To test the class, we change the $name property on line 23 and then call getInstance() once again on line 25. We confirm that the $second variable contains a reference to the same instance of Shop on line 26 by printing $shop->name.

    [ Team LiB ] Previous Section Next Section