`self::` vs. `static::` in PHP: A Deep Dive into Late Static Binding

Published: 2025-11-18
Author: DP
Views: 12
Category: PHP
Content
## Introduction In PHP Object-Oriented Programming (OOP), `self` and `static` are two common keywords used to access static members within a class. However, their differing behaviors in inheritance scenarios often cause confusion for developers and can lead to hard-to-trace bugs if misused. This article, using a classic example from a `wiki.lib00.com` project, will break down their differences and help you fully grasp PHP's **Late Static Binding** mechanism. --- ## The Core Difference at a Glance Simply put, the difference lies in the timing of the "binding": * `self::$property`: **Static Binding**. `self` always refers to the class where the code is **defined**. This relationship is determined at compile time. * `static::$property`: **Late Static Binding**. `static` refers to the class that was actually **called at runtime**. This relationship is determined dynamically when the code is executed. --- ## The Code Example That Explains Everything The best way to understand late static binding is through a practical example. Let's imagine we're building a simple ORM (Object-Relational Mapping) base model for the `lib00` platform. Each model needs a `$table` property to specify its corresponding database table name. ```php <?php namespace WikiLib00\Framework; abstract class BaseModel { // Define a default table name in the parent class protected static string $table = 'base_models'; // Get the table name using `self` public static function getSelfTable(): string { // `self` always refers to BaseModel because it's defined here return self::$table; } // Get the table name using `static` public static function getStaticTable(): string { // `static` refers to the class called at runtime (e.g., UserModel or ProductModel) return static::$table; } } class UserModel extends BaseModel { // Override the parent's static property in the child class protected static string $table = 'users'; } class ProductModel extends BaseModel { // Override the parent's static property in the child class protected static string $table = 'products'; } // --- Check the results --- // Calling from UserModel echo 'UserModel::getSelfTable(): ' . UserModel::getSelfTable(); // Outputs: base_models echo "\n"; echo 'UserModel::getStaticTable(): ' . UserModel::getStaticTable(); // Outputs: users echo "\n\n"; // Calling from ProductModel echo 'ProductModel::getSelfTable(): ' . ProductModel::getSelfTable(); // Outputs: base_models echo "\n"; echo 'ProductModel::getStaticTable(): ' . ProductModel::getStaticTable(); // Outputs: products ``` --- ## Analyzing the Output * **`UserModel::getSelfTable()`** returns `'base_models'`. Because the `getSelfTable()` method is defined in `BaseModel`, the `self` keyword is "locked" to the `BaseModel` class. No matter which child class calls it, it will only return the `$table` property defined in `BaseModel`. * **`UserModel::getStaticTable()`** returns `'users'`. The `static` keyword enables late static binding. It doesn't lock to a class immediately. Instead, it waits until runtime to see who actually **called** the `getStaticTable()` method. In this case, the caller is `UserModel`, so `static` resolves to `UserModel` and returns its `$table` property. --- ## When to Use `self` vs. `static`? Once you understand the difference, making the choice becomes simple: * **Use `self`**: When you explicitly need to refer to a constant or static member defined in the **current class itself**, and you do not want it to be changed by the inheritance chain. For example, a fixed version number or a configuration item defined in a base class. * **Use `static`**: When you are designing **extensible base classes or frameworks** where methods in the parent class need to flexibly use static members overridden in child classes. Table names in an ORM, or class names in a Factory pattern, are classic use cases for `static`. This approach makes the code more flexible and adheres to the Open/Closed Principle. --- ## Conclusion The `static::` keyword is the key to PHP's Late Static Binding, significantly enhancing code flexibility and reusability. A key recommendation from the author `DP` is to prefer `static` for referencing static members when writing inheritable classes. This will allow you to build more powerful and adaptable systems.