Use $this to refer to the current object. Use self to refer to the current class. In other words, use $this->member for non-static members, use self::$member for static members.

In the example below, sayHello() and sayGoodbye() are using self and $this difference can be observed here.

class Person {
    private $name;

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

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

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

static refers to whatever class in the hierarchy you called the method on. It allows for better reuse of static class properties when classes are inherited.

Consider the following code:

class Car {
    protected static $brand = 'unknown';
    
    public static function brand() {
         return self::$brand."\\n";
    }
}

class Mercedes extends Car {
    protected static $brand = 'Mercedes';
}

class BMW extends Car {
    protected static $brand = 'BMW';
}

echo (new Car)->brand();
echo (new BMW)->brand();
echo (new Mercedes)->brand();

This doesn’t produce the result you want:

unknown

unknown

unknown

That’s because self refers to the Car class whenever method brand() is called.

To refer to the correct class, you need to use static instead:

class Car {
    protected static $brand = 'unknown';
    
    public static function brand() {
         return static::$brand."\\n";
    }
}

class Mercedes extends Car {
    protected static $brand = 'Mercedes';
}

class BMW extends Car {
    protected static $brand = 'BMW';
}

echo (new Car)->brand();
echo (new BMW)->brand();
echo (new Mercedes)->brand();

This does produce the desired output:

unknown

BMW

Mercedes

See also http://stackoverflow.com/documentation/php/504/classes-and-objects/5420/late-static-binding#t=201608122306182437362

The singleton