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.

Leave A Comment