Late Static Binding (LSB) allows a static method to refer to the class it was called on, rather than the class in which it was defined. Use static:: instead of self:: to enable LSB.
self:: always refers to the class where the method is physically defined.
static:: refers to the class that was invoked at runtime.
Essential for correct behaviour in static factory methods and singleton patterns when used with inheritance.
Example
<?php
class Model
{
// Using self:: — WRONG for inheritance
public static function createSelf(): static
{
return new self(); // Always creates Model, never the child
}
// Using static:: — CORRECT for inheritance (LSB)
public static function create(): static
{
return new static(); // Creates the actual called class
}
// get_called_class() equivalent: static::class
public static function getClass(): string
{
return static::class; // returns the runtime class name
}
}
class User extends Model
{
public string $type = 'user';
}
class Admin extends Model
{
public string $type = 'admin';
}
$model = Model::create(); // instanceof Model
$user = User::create(); // instanceof User ✓
$admin = Admin::create(); // instanceof Admin ✓
echo User::getClass(); // User
echo Admin::getClass(); // Admin
// Practical: active-record style finder
class BaseRecord
{
private static array $store = [];
public static function find(int $id): ?static
{
return static::$store[$id] ?? null;
}
public static function save(int $id, static $record): void
{
static::$store[$id] = $record;
}
}
class UserRecord extends BaseRecord {}
$u = new UserRecord();
UserRecord::save(1, $u);
$found = UserRecord::find(1); // returns UserRecord instance
Pro Tip
Tip: A quick rule: if you want the method to be "self-aware" of the class it was called on (even through inheritance), use static::. If you always want the class where the code lives, use self::. For factory methods and singletons in base classes, almost always use static::.