Using PHP late static binding to define static arrays as subsets for child classes

OK, the title might sound a little confusing, but the concept it relatively simple. Basically it’s using an array in a child class that contains some of the items that appear in the array in the parent class.

Which just means you have a list of all of the things in the parent, and a list of some of those things in every child. Like a list of options such as colours, types, etc.

Imagine that you have a class that represents all the cars you sell:

class Cars

To make sure that an enumerated database field matches up when you pick the colour of the car, you use class constants; this is so that when you set you use the same constant, as opposed to typing it in each time (which reduces error, and means you can change it in one place only)

class Car
{
const COLOUR_GREEN = 'green';
const COLOUR_RED = 'red';
const COLOUR_YELLOW = 'yellow';
const COLOUR_BLUE = 'blue';

If you want to find out what colours the cars are available in, you could use an array. Because you can’t declare constant arrays (because they aren’t scalar) you could use a variable; using a static variable will allow you to use it in static methods.

class Car
{

const COLOUR_GREEN = 'green';
const COLOUR_RED = 'red';
const COLOUR_YELLOW = 'yellow';
const COLOUR_BLUE = 'blue';

static array $colours = array(
COLOUR_GREEN,
COLOUR_RED,
COLOUR_YELLOW,
COLOUR_BLUE,
);

}

Then, if you want to make child classes of the cars class, to represent each type of car, you don’t need to redine the constants; all the types of cars can be those colours. However, each type of car might not be available in every colour; the colours are the same but which colours are available are different.

For example if you had trucks that were available in green, red and yellow, and vans that were available in red and blue.

class Truck extends Car
{

static array $colours = array(
COLOUR_GREEN,
COLOUR_RED,
COLOUR_YELLOW,
);

}

class Van extends Car
{

static array $colours = array(
COLOUR_RED,
COLOUR_BLUE,
);

}

This might look all well and dandy, but the problem comes when you check what is in self::$colours in a static method of the child class. Despite the values being different in the child class, it will still contain the values in the class where it was originally declared.

Therefore, if you ran the following method:

static method colours()
{

print_r(self::$colours);

}

You would get the following result in all 3 classes, even if you declared self::colours() in every class.

Array
(
    [0] => green
    [1] => red
    [2] => yellow
    [3] => blue
)

To make sure that PHP gets the values from the most recently declared (in the class hierarchy) version of that array, is to use the static keyword.

static method colours()
{

print_r(static::$colours);

}

Using the static keyword, you would only need to write the static colours() in the parent class, as it will still use the static variable in the child class if it is called from the child class, even if the method is declared in the parent class. Calling Car::colours() will tell you all of the colours that are available, Truck::colours() will tell you what colours trucks come in, and likewise with Van::colours()

Note that you do need PHP 5.3 to make this work.

p.s. I wouldn’t actually put colour constants in a car class! It was just the first example that I could think of that wasn’t what I actually used it for at work…

4 comments

Leave a Reply to Andrew Kirkpatrick Cancel reply

  • I’m so glad you posted this! I know this blog post is old, but it’s still useful even today!

  • am using PHP 5.6. and it doesn’t work as described. it put out just the static array in defined in the class with self, I miss the point.
    Besides Keys must be in quotes and
    static >>array<< raise error : Parse error: syntax error, unexpected 'array' (T_ARRAY), expecting variable (T_VARIABLE) in ..

    • The array keys are defined as constants in the base class, which are themselves string literals. The example is trying to demonstrate how to override a parent class static array in a child class and how to call this within the child (static) as opposed to where it was originally declared in the parent (self)