Late Static Binding
Late static binding (static:: vs self::) lets parent classes defer method resolution to the child class. It's the foundation of the fluent factory pattern used by every modern PHP framework.
class Model {
protected static string $table;
// self:: would always resolve to Model — wrong!
// static:: resolves to whatever class called the method
public static function find(int $id): static {
$table = static::$table;
$row = DB::query("SELECT * FROM {$table} WHERE id = ?", [$id]);
return static::hydrate($row); // Returns User, not Model
}
public static function create(array $data): static {
// static:: ensures the child class is instantiated
$instance = new static();
foreach ($data as $key => $value) {
$instance->$key = $value;
}
$instance->save();
return $instance;
}
}
class User extends Model {
protected static string $table = 'users';
}
class Post extends Model {
protected static string $table = 'posts';
}
$user = User::find(1); // Returns User instance, queries 'users' table
$post = Post::create([ // Returns Post instance
'title' => 'Hello',
]);
The static return type (PHP 8.0) completed this feature by letting you declare that a method returns an instance of the called class, not the declaring class. This is what makes fluent builder patterns type-safe.
Significance: Polymorphism
Late static binding is the mechanism that makes framework base classes work. Without it, factory methods, fluent builders, and the Active Record pattern would be impossible to implement with proper type safety. It's a quiet feature that powers some of PHP's most elegant patterns.