override a static variable

The principle is called "late static binding", and was introduced in PHP 5.3.0; with the self keyword to access the property defined in the calling class within the inheritance tree, or static to access the property defined in the child class within that inheritance tree.

class person
{
    protected static $todo ="nothing";

    public function __construct(){}

    public function get_what_todo()
    {
        echo static::$todo;  // change self:: to static::
    }
}

class student extends person
{
    protected static $todo ="studying";
}

class teacher extends person
{
    protected static $todo ="marking";
}

class guest extends person
{
}

$s = new student();
$s->get_what_todo(); // this will show the "studying" from the instantiated child class

$t = new teacher();
$t->get_what_todo(); // this will show the "marking" from the instantiated child class

$g = new guest();
$g->get_what_todo(); // this will show the "nothing" from the parent class,
                     // because $todo is not overriden in the child class

you can try set variable in construction

class person
{
    protected static $todo = null;

    public function __construct(){
        self::$todo = "nothing";
    }

    public function get_what_todo()
    {
        echo self::$todo;
    }
}

class student extends person
{
    public function __construct() {
       self::$todo = "student";
    }
}

$s = new student();
$s->get_what_todo();

The reliable way to override a static variable is to do it by redeclaring it. Some people may suggest modifying it in the construct method, but I don't think that's reliable.

It won't reflect the changes until the class is constructed at least once. And of course, in class methods, don't forget to call the static variable using "static::" instead of "self::" when you want to always access the overridden variable.

Here's an example of what I mean: The class Foo is the base class, the class Bar is changing the variable inside its constructor, and the class Baz is overriding the variable in its declaration.

class Foo
{
    public static $a = "base";
}

class Bar extends Foo
{
    function __construct()
    {
        self::$a = "overridden";
    }
}

class Baz extends Foo
{
    public static $a = "overridden";
}

echo 'Foo: ' . Foo::$a . '<br>';
echo 'Bar: ' . Bar::$a . '<br>';
echo 'Baz: ' . Baz::$a . '<br>';
new Bar();
echo 'Bar after instantiation: ' . Bar::$a;

This is the output from phptester.net

Foo: base
Bar: base
Baz: overridden
Bar after instantiation: overridden

As you can see, Bar's way of changing the variable isn't taking effect until after the constructor is called at least once.

EDIT: However, there is another way to edit a variable permanently and reliably: do it after the class declaration. This is especially handy if you only need to modify a variable and not completely override it, like for example an array. It feels a bit dirty, but in theory should work everytime.

class Foo
{
    public static $a = [
        'a' => 'a'
    ];
}

class Bar extends Foo
{
    public static $a;
}
Bar::$a = Foo::$a;
Bar::$a['b'] = 'b';

echo 'Foo: ' . print_r(Foo::$a, true) . '<br>';
echo 'Bar: ' . print_r(Bar::$a, true) . '<br>';

This is the output from phptester.net

Foo: Array ( [a] => a )
Bar: Array ( [a] => a [b] => b ) 

EDIT 2: This last method also gets picked up by ReflectionClass::getStaticPropertyValue in my tests.