PHP Pandas: Statics

← Back to Index

Static is that pixely-dotty stuff that you get on your television before you tune all your channels in. Right, next chapter. Wait, you're a young handsome/beautiful/both developer aren't you? You're going to be too young to know about tuning terrestrial televisions. Let's take a look at static methods and properties instead then, shall we?

Static Properties

First you're going to need a class.

<?php

class RedPanda
{

}

There she is, bushy tail, fine fluffy coat... what a fine specimen of a class! Normally, we'd have to create an instance of our class to use it, wouldn't we? Something like this...

<?php

$panda = new RedPanda;

As we've learned previously, each instance can contain different values and states to other instances of the RedPanda class. For example, if the class had a name property, one instance might have the name 'Hamish' while another might be called 'Daniel'. The instances of the classes have state.

Well... unless you cheat a little. You see, the class itself can have state. Let's add a static property to our RedPanda class, shall we?

<?php

class RedPanda
{
    /**
     * The panda's name!
     *
     * @var string
     */
    public static $name;
}

By adding the keyword static after our new property's scope, we've made it static. What does that mean exactly? Well, we can actually use this property without having to create an instance of the class. Here's a simple example...

<?php

RedPanda::$name = 'Hamish';

echo RedPanda::$name;

In the example above, you'll notice that we're not creating an instance of RedPanda. Instead, we're setting the $name static property using the 'scope resolution operator'... or.. ::. Don't forget that you still need to use the $, when pointing out the property. This is a common gotcha, since $this->name wouldn't require the dollar sign.

Using this method, we can set and retrieve static properties on the class, as if they were public instance properties. That's not all! The instances that we create of this class will also retain the state of that variable across all instances. For example, let's take a look at the following snippet.

<?php

RedPanda::$name = 'Hamish';

$panda = new RedPanda;

echo $panda::$name;

In the example above, we're setting the static parameter to 'Hamish' on the class directly. We then create a new instance of the class, and echo the static property directly from that instance. We receive the result 'Hamish'. No matter whether you are working with the class directly, or an instance of that class, the state of that variable will be common across all circumstances.

Do you think you're limited to only static properties? Oh no! Think again dear reader...

Static Methods

Classes may also have methods that are static. Let's create an example.

<?php

class RedPanda
{
    /**
     * Make the panda be cute!
     *
     * @return void
     */
    public static function beCute()
    {
        echo 'The Red Panda rolls around in the snow.';
    }
}

Once again, we simply add the keyword static to the method declaration to make it a static one. Now let's try to use this method on the class itself, rather than an instance of a RedPanda class.

<?php

RedPanda::beCute();

The Red Panda rolls around in the snow.

Aww, isn't that sweet! Because our method is defined as static, we can use it without having to create a class instance.

Now let's setup a trap... no not for the Panda! For ourselves. Consider the following example.

<?php

class RedPanda
{
    public $name = 'Hamish';

    public static function beCute()
    {
        $pandaName = $this->name;
        echo "{$pandaName} rolls around in the snow.";
    }
}

You'll notice that the function is still static, but we've added a class property that is not static. The static method tries to retrieve this property using $this->name. What do you think will happen when we call RedPanda::beCute()?

PHP Fatal error:  Using $this when not in object context in [file]

Oh dear! Non-static properties belong to instances of classes. They can hold different values in each instances. We're calling our static method on the class itself, so it has no instance to play with. Since there is no instance, $this resolves to nothing. Any attempts to use it will result in a PHP fatal error.

This also means that we can't call other non-static methods from a static method on a class, because we'd have to use $this->otherMethod() to do so.

Does that mean that our static methods can't call to other methods? Well not entirely. Our static methods can call to other static methods. Here's an example.

<?php

class RedPanda
{
    public static function eat()
    {
        return self::eatLeaves();
    }

    private static function eatLeaves()
    {
        return 'The Panda munches on some tasty leaves.';
    }
}

Right, let's run through this. We have a public static method called eat(), this calls to the eatLeaves() method and returns the result. Note that the eatLeaves() method is private, and thus cannot be called directly on the class. It can only be called from within another method of the class.

We're using the self keyword in the above example. It's used to refer to itself, or the current class. So self::eatLeaves() means, please make a static call to the eatLeaves() method of this class.

When we run RedPanda::eat() we get..

The Panda munches on some tasty leaves.

Many developers use these public static methods to create instances of the classes that they are attached to. For example...

<?php

class RedPanda
{
    protected $name;

    public function __construct($name = null)
    {
        $this->name = $name;
    }

    public static function make()
    {
        return new self('Hamish');
    }

    public function getName()
    {
        return $this->name;
    }
}

In the above example, our RedPanda class takes an optional $name parameter through it's constructor. Then, it sets the $name protected property to the value you have passed. The public getName() function can be used to access the name of the panda.

We've also got the make() public static method, which returns new self() to create a new instance of the current class, and return it. It even passes 'Hamish' as the name, so we can use RedPanda::make() to create a new Hamish panda instance quickly.

We mentioned that you can't access instance methods from a static method, but the reverse is perfectly acceptable! For example, you could use self::staticMethodHere() from a non-static method and PHP would be perfectly happy.

Late Static Binding

Late static binding is a feature that was introduced in version 5.3 of PHP. It has a really confusing name, so let's demonstrate with code instead. First we need two classes, with a touch of inheritance.

<?php

class Panda
{
    public static function whoAmI()
    {
        return self::getType();
    }

    public static function getType()
    {
        return 'I am a Giant panda!';
    }
}

class RedPanda extends Panda
{
    public static function getType()
    {
        return 'I am a Red panda!';
    }
}

Here we have two classes. Panda is our base class, and represents a giant panda. RedPanda extends from Panda, and represents a red panda... duh. The base class has a static method called 'getType()', which tells you it's a Giant Panda. This method is overridden in the RedPanda class to let you know that it's a RedPanda.

We can use the static whoAmI() method on both classes to find out what type of panda we have. Let's call it now...

<?php

echo Panda::whoAmI() . PHP_EOL;
echo RedPanda::whoAmI();

Upon running this snippet, we receive the following output.

I am a Giant panda!
I am a Giant panda!

Wait, why are they both Giant pandas!? We've overridden the getType() method in the RedPanda class, so shouldn't PHP respect the inheritance?

Actually, the self keyword will only reference the base class. If we wish to use late static binding, we need to replace the self keyword with static. Yes, I know... we sure are overusing this keyword. Let's take a look at the transformation.

<?php

class Panda
{
    public static function whoAmI()
    {
        return static::getType();
    }

    public static function getType()
    {
        return 'I am a Giant panda!';
    }
}

class RedPanda extends Panda
{
    public static function getType()
    {
        return 'I am a Red panda!';
    }
}

You'll notice that all we've done is replaced self with static. Now let's try executing the code once more.

I am a Giant panda!
I am a Red panda!

There we go! PHP has now respected the inheritance, and the overriding of the getType() method. The world is once again... dandy!


Understanding the concept of statics can be a tricky business. It was not until very late into my career as a PHP developer that I started to use them effectively. If you find this chapter a little confusing, I'd suggest moving ahead using class instances for now, and coming back to this chapter with a little more experience.

For now at least, you know how to identify static properties and methods by their keyword.

My books are available online for free to encourage learning. However, if you'd like for me to keep writing, then please consider buying a digital copy over at Leanpub.com.

It's available in PDF, ePub, and Kindle format, and contains a bunch of extras that you won't find on the site. I have a full-time job, and I write my books in my spare time. Please consider buying a copy so that I can continue to write new books from the comfort of my sofa!