self, static, and parent in PHP — What's the Real Difference and When to Use Each
In PHP, object-oriented programming gives us several powerful keywords—self, static, and parent—to refer to classes within the class hierarchy. While they may seem similar, each has very specific behaviors, especially when dealing with inheritance, method resolution, and instantiation.
Understanding these keywords deeply is crucial for writing clean, predictable, and extensible code.
🔹 self: The Declaring Class
self refers to the class where the code is written, not where it is called from. This is a compile-time reference.
class A {
    public static function who() {
        echo "A\n";
    }
    public static function test() {
        self::who();
    }
}
class B extends A {
    public static function who() {
        echo "B\n";
    }
}
B::test(); // Output: A
Even though B extends A, calling B::test() still prints A because self::who() is bound to class A. This is not polymorphic.
🔹 static: Late Static Binding
static uses late static binding, meaning it resolves to the class that was actually called at runtime, even if it’s a subclass. This is runtime-bound.
class A {
    public static function who() {
        echo "A\n";
    }
    public static function test() {
        static::who();
    }
}
class B extends A {
    public static function who() {
        echo "B\n";
    }
}
B::test(); // Output: B
Here, static::who() correctly resolves to class B. This is polymorphic and what you want when you expect child classes to override behavior.
Use static when:
- You expect inheritance
 - You want the behavior to be overridden correctly
 - You are working with factories, fluent APIs, or interfaces with 
staticreturn types 
🔹 parent: Accessing the Superclass
parent is used to call methods from the immediate parent class. It’s strictly for accessing the parent’s implementation, often inside an override.
class A {
    public function greet() {
        echo "Hello from A\n";
    }
}
class B extends A {
    public function greet() {
        parent::greet();
        echo "And hello from B\n";
    }
}
$b = new B();
$b->greet();
Output:
Hello from A
And hello from B
Use parent when:
- You override a method but still want to call the parent’s version
 - You're working in an inheritance chain and want to build on base behavior
 
🔍 Comparison Summary
| Keyword | Bound At | Refers To | Use Case | 
|---|---|---|---|
| self | Compile-time | Class where code is written | Internal helper methods, fixed behavior | 
| static | Runtime | Class that was called | Factory methods, polymorphic behavior | 
| parent | Compile-time | Immediate parent class | Overridden methods needing base behavior | 
✅ Real-World Considerations
selfcan break polymorphism. Be cautious when writing base class methods that useself, as they won't behave well when extended.staticis powerful but introduces complexity. Use it for factories or fluent interfaces when subclassing is expected.parentis safe but very specific. Don't use it unless you're overriding methods and still need parent logic.
💡 Bonus Tip
When using static methods that return new instances (new static()), avoid new self() unless you're sure that the method won’t be extended or overridden. Even in a final class, using static is often more future-proof.
Understanding these keywords isn't just about syntax—it’s about design. Use the right keyword for the right behavior, and your codebase will be easier to maintain, less error-prone, and ready for change.
Comments ()