In PHP, self:: and static:: are used to reference class members (methods, properties, constants) in static contexts. Their behavior differs due to late static binding, a mechanism that determines the target class at runtime.
1 ) self::add()
- What it does: self:: refers to the class where the method is defined (at compile-time). It does not account for inheritance or overrides in child classes.
- Behavior: If a child class overrides add(), self::add() in the parent class will always call the parent’s version, even when invoked from the child class.
- Use case: When you explicitly want to use the current class’s implementation, ignoring any overrides in child classes.
Example:
class A {
public static function add() {
echo "Called from A";
}
public static function callAdd() {
self::add();
}
}
class B extends A {
public static function add() {
echo "Called from B";
}
}
B::callAdd(); // Outputs: Called from A
2) static::add() (Late Static Binding)
- What it does: static:: uses late static binding to resolve the class at runtime. It refers to the class that was called (e.g., a child class if the method is inherited).
- Behavior: If a child class overrides add(), static::add() will call the child’s version when invoked through the child class.
- Use case: Use static:: to allow child classes to override static methods/properties while ensuring the parent class uses the child’s implementation.
Example:
class A {
public static function add() {
echo "Called from A";
}
public static function callAdd() {
static::add();
}
}
class B extends A {
public static function add() {
echo "Called from B";
}
}
B::callAdd(); // Outputs: Called from B
When to Use Which:
- self:: Use when you want to lock the reference to the current class, ignoring overrides. Example: Utility methods, internal class logic that shouldn’t change in subclasses.
- static:: Use when designing extensible classes where child classes should override behavior. Example: Factory methods, template methods, or dependency injection where child classes customize behavior.
Best Practices
- Use self:: for final or non-overridable logic.
- Use static:: for polymorphic behavior in inheritance hierarchies.
- Avoid mixing self:: and static:: inconsistently within the same class to prevent confusion.