Tuesday, November 18, 2014

What are static bindings in PHP - Using self:: versus static::

[1] Why an abstract horse?  See below.

What are static bindings?

Static bindings are functions or variables that can be called on a class that don't need an object created to use them first.  For example, you don't need to use the new operator to call a static method or access a static variable.  These methods exist the first time the class is loaded by the php process and are accessed using the '::' accessor.

How and when to use late static binding in PHP

Late static bindings should be used anytime you are likely to want to redefine or override static objects in children class.  In those cases you will use the static keyword which is a signal to php to check the child class for the appropriate overridden function or variable before it goes up the chain in checking the parent classes.

If you are sure the static function in the base class isn't going to change, or you don't want it to change, then you should consider using the self keyword to access the item.

<?php

abstract class booger {
    abstract function b();
    public static function a() { echo("base class function<br />"); }
    public function c() { self::a();}
    public function d() { static::a();}
}

class goober extends booger{
    public function b() { echo("extended class function<br />"); }
    public static function a() { echo("late static binding<br />"); }
}

$goob = new goober();
$goob::a();
$goob->b();
$goob->c();
$goob->d(); //this is the line that actually uses the late static binding
goober::a();

?>


OUTPUT:

late static binding
extended class function
base class function
late static binding
late static binding



The first line $goob::a() is just a regular overridden function call and does not use the static keyword for the access.  Similarly, $goob->b() is regular method call to a function that was required to be created because of the abstract keyword.

$goob->c() makes use of the self keyword.  This means that the whichever class the keyword is found in is the one that is searched for the requested method.  That is why it shows the output from the base class function.
 

$goob->d() makes use of the static keyword which shows how although the same function a() is called, that since the static keyword was used php knows to check not the base class but the calling class first for the requested function.  That was the desired behavior we were looking for in this case.

Summary

Generally, in most cases static will be the correct keyword to use since the programmer often expects the class to prefer to use the functions in the children classes over those in the parent class.  There are exceptions in situations where self is more appropriate such as when you don't ever plan on calling a particular function from a child class and only the parent class.

Some Gotchas

Please note incorrect order or positioning of the classes in your code can affect the interpreter and can cause a Fatal error:
Class 'YourClass' not found 

This can happen when there are multiple levels of abstraction and the base classes are out of order in the source code.  

For example:
 
<?php

abstract class horse extends animal {
    public function get_breed() { return "Jersey"; }
}

class cart extends horse {
    public function get_breed() { return "Wood"; }
}
 
abstract class animal {
    public abstract function get_breed();
}

$cart = new cart();
print($cart->get_breed());
?>

this outputs:
Wood

 
However, if you put the cart before the abstract horse (literally):
 
<?php
//same code, just in a different order
class cart extends horse {
    public function get_breed() { return "Wood"; }
}

abstract class horse extends animal {
    public function get_breed() { return "Jersey"; }
}
 
abstract class animal {
    public abstract function get_breed();
}

$cart = new cart();
print($cart->get_breed());

?>

this throws an error:
Fatal error: Class 'horse' not found
So, when using multiple levels of abstraction, be careful of the positioning of the classes within the source code - and don't put the cart before the abstract horse.

[1] The abstract horse image was provided by pptbackgroundstemplates.