What Is The Difference Between Self And $this In PHP?

Published October 7, 2024

Problem: Understanding Self vs $this in PHP

PHP developers often get confused when choosing between self and $this in their code. These keywords have different uses in object-oriented programming, but their differences can be unclear. This can lead to errors or inefficient code.

The Core Differences Between Self and $this

Answer: Key Distinctions and Use Cases

In PHP, self and $this have different uses in object-oriented programming. Knowing their differences helps you use them correctly.

self refers to the current class. You use it to access static properties and methods within the class. For example:

class MyClass {
    private static $staticProperty = 'Hello';

    public function getStaticProperty() {
        return self::$staticProperty;
    }
}

$this refers to the current object instance. You use it to access non-static properties and methods of the object. For example:

class MyClass {
    private $instanceProperty = 'World';

    public function getInstanceProperty() {
        return $this->instanceProperty;
    }
}

Use self when you need to access static properties and methods. Static elements belong to the class itself, not to any specific instance of the class. You can access them without creating an object of the class.

Use $this when you need to access non-static properties and methods. These elements belong to a specific instance of the class and require an object to be created before you can access them.

Knowing these differences helps you write better PHP code and avoid common mistakes in object-oriented programming.

Tip: When to Use Late Static Binding

If you need to reference the called class in a context of static inheritance, use the static keyword instead of self. This is known as late static binding:

class ParentClass {
    public static function whoAmI() {
        echo static::class;
    }
}

class ChildClass extends ParentClass {}

ChildClass::whoAmI(); // Outputs: ChildClass

Practical Examples of Self and $this Usage

Demonstrating Correct Usage

Here are examples that show the correct use of self and $this in PHP classes:

Using self for static members:

class Calculator {
    private static $pi = 3.14159;

    public static function getPI() {
        return self::$pi;
    }
}

echo Calculator::getPI(); // Outputs: 3.14159

In this example, we use self::$pi to access the static property $pi within the Calculator class.

Using $this for non-static members:

class User {
    private $name;

    public function setName($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

$user = new User();
$user->setName("John");
echo $user->getName(); // Outputs: John

Here, we use $this->name to access the non-static property $name of the User object.

Tip: Use self for constants

When working with class constants, always use self:: to access them within the class, as constants are implicitly static:

class MathConstants {
    const PI = 3.14159;

    public static function getPI() {
        return self::PI;
    }
}

Common Mistakes to Avoid

Developers sometimes make mistakes when using self and $this. Here are some common errors to avoid:

Incorrect use of self with non-static members:

class Wrong {
    private $nonStaticVar = "I'm not static";

    public function getVar() {
        return self::$nonStaticVar; // This is incorrect
    }
}

This code will result in an error because self:: is used to access a non-static property.

Incorrect use of $this with static members:

class AlsoWrong {
    private static $staticVar = "I'm static";

    public function getVar() {
        return $this->staticVar; // This is incorrect
    }
}

This code will not work as expected because $this-> is used to access a static property.

By understanding these examples and common mistakes, you can write more reliable PHP code using self and $this correctly.

Impact on Inheritance and Polymorphism

Self vs $this in Inherited Classes

When working with inheritance in PHP, self and $this behave differently, affecting method calls in child classes and enabling polymorphic behavior.

self affects method calls in child classes by referring to the class where it's used, regardless of inheritance. When you use self to call a method in a parent class, it will call the method as defined in that parent class, even if it's overridden in a child class. For example:

class ParentClass {
    public static function whoAmI() {
        echo "I am ParentClass";
    }

    public function callSelf() {
        self::whoAmI();
    }
}

class ChildClass extends ParentClass {
    public static function whoAmI() {
        echo "I am ChildClass";
    }
}

$child = new ChildClass();
$child->callSelf(); // Outputs: I am ParentClass

In this example, calling callSelf() on a ChildClass object outputs "I am ParentClass" because self refers to ParentClass.

$this enables polymorphic behavior by referring to the current object instance, allowing method calls to be resolved at runtime based on the object's type. When you use $this to call a method, it will call the most specific implementation of that method for the current object. For example:

class ParentClass {
    public function whoAmI() {
        echo "I am ParentClass";
    }

    public function callThis() {
        $this->whoAmI();
    }
}

class ChildClass extends ParentClass {
    public function whoAmI() {
        echo "I am ChildClass";
    }
}

$child = new ChildClass();
$child->callThis(); // Outputs: I am ChildClass

In this case, calling callThis() on a ChildClass object outputs "I am ChildClass" because $this refers to the ChildClass instance, and the overridden whoAmI() method in ChildClass is called.

Understanding these differences is important when designing class hierarchies and implementing polymorphic behavior in PHP. Using $this allows for more flexible and dynamic code, while self provides a way to access specific implementations in parent classes when needed.

Tip: Using static:: for Late Static Binding

When you need to reference the called class in a static context, use static:: instead of self::. This allows for late static binding, which resolves the method call at runtime based on the class that was initially called. For example:

class ParentClass {
    public static function getClassName() {
        return static::class;
    }
}

class ChildClass extends ParentClass {}

echo ParentClass::getClassName(); // Outputs: ParentClass
echo ChildClass::getClassName();  // Outputs: ChildClass

Advanced Concepts: Late Static Binding

Introduction to Static::

Late static binding is a PHP feature that extends the functionality of static methods and properties in class inheritance. It uses the static:: keyword, which is often better than self:: in certain cases.

You should use static:: instead of self:: when you want to reference the class that was called at runtime, rather than the class where the method is defined. This is useful in inheritance situations where you want to keep flexibility in method calls.

Here are some examples of late static binding in PHP:

  1. Accessing overridden static methods:
class ParentClass {
    public static function getClassName() {
        return static::class;
    }
}

class ChildClass extends ParentClass {}

echo ParentClass::getClassName(); // Outputs: ParentClass
echo ChildClass::getClassName();  // Outputs: ChildClass

In this example, static::class returns the name of the class that was called, allowing for dynamic resolution of the class name.

  1. Creating factory methods:
class Animal {
    public static function create() {
        return new static();
    }
}

class Dog extends Animal {}

$animal = Animal::create(); // Creates an Animal instance
$dog = Dog::create();       // Creates a Dog instance

Here, static:: allows the create() method to return an instance of the class that called it, making it a flexible factory method.

  1. Overriding static properties:
class ParentClass {
    protected static $value = 'parent';

    public static function getValue() {
        return static::$value;
    }
}

class ChildClass extends ParentClass {
    protected static $value = 'child';
}

echo ParentClass::getValue(); // Outputs: parent
echo ChildClass::getValue();  // Outputs: child

In this case, static:: allows the getValue() method to access the $value property of the class that called it, respecting overrides in child classes.

Late static binding with static:: provides more flexibility in static method and property inheritance, allowing for more dynamic behavior in your PHP classes.

Tip: Using static:: in Trait Methods

When using traits in PHP, static:: can be particularly useful. It allows trait methods to reference the class that is using the trait, rather than the trait itself. This enables more flexible and reusable trait code.

trait Loggable {
    public static function log($message) {
        echo static::class . ": " . $message . "\n";
    }
}

class UserManager {
    use Loggable;
}

UserManager::log("User created"); // Outputs: UserManager: User created