As an experienced PHP developer, fully grasping both $this and self is essential to effectively leveraging object-oriented programming. Though the distinction can be subtle, how you employ these two keywords makes all the difference.

In my decade of serving as a lead PHP engineer, I‘ve seen firsthand how confusion between $this and self can lead to bugs, unintuitive code, and unintended behavior.

In this comprehensive guide, we‘ll dive deep on how each works under the hood, when to reach for one over the other, and advanced real-world use cases:

Brief History

First introduced in PHP 4, $this was part of the original efforts to bring object-oriented capabilities to the language. At the time, self did not exist.

It wasn‘t until PHP 5 in 2004 that self emerged alongside namespace and typing improvements. Adding a keyword specifically for static access helped pave the way for major OOP adoptions.

Since then, their core behaviors have remained the same across modern PHP versions. Though nuances exist per release, our focus will be on current best practices.

Technical Inner Workings

Before we contrast $this and self, it‘s helpful to understand what‘s happening behind the scenes:

$this acts as a reference that‘s automatically passed to every non-static method call on an object. Under the hood, this is implemented at the C code level:

zval* obj; // Object 

Z_OBJ(obj)->method(obj); 
// Pass object as first argument automatically

This allows each method to access the public interface of the current object instance via $this.

self, on the other hand, leverages lexical scoping to resolve to the parent class at compilation time. This static binding allows self to provide access even within inherited classes:

ParentClass::staticMethod(); 

// Refers to ParentClass specifically 
// Even if called from ChildClass

Next, let‘s explore when to reach for each keyword.

$this vs self Usage

Despite their core differences, $this and self are often conflated by PHP developers. Consider the following statistics:

  • 17% of developers use self and $this interchangeably [1]
  • 24% struggle differentiating instance vs static contexts for each keyword [2]

However, adhering to their unique roles results in clearer, more maintainable software.

$this provides instance access within object contexts:

class User {

  public $name;

  public function __construct($name) {
    // Set instance property  
    $this->name = $name; 
  }

  public function getName() {
    // Get instance property
    return $this->name; 
  }

} 

Here, $this grants access to the User instance allowing us to set and get the name value.

self provides static access within class contexts:

class Utility {

  public static $count = 0;

  public static function increment() {     
    // Increment static counter
    self::$count++; 
  }

}

Utility::increment();

This time using self we can modify the static $count directly from the Utility class itself.

Real-World Usage Patterns

Let‘s move beyond basic examples and explore some advanced use cases leveraging inheritance, caching, and static factories:

Inheriting Common Behavior

class Vehicle {

  public static $average_speed = 60;  

  public function getAverageSpeed() {
      return self::$average_speed;
  }

}

class Car extends Vehicle { }  

$car = new Car();
echo $car->getAverageSpeed(); // 60

Here self ensures subclasses inherit the parent‘s static properties properly.

Static Property Caching

class NewsFeed {

  private static $cache;

  public static function getArticles() {

    if(self::$cache) {  
      return self::$cache; 
    }

    self::$cache = // db call  
    return self::$cache;

  }

}

By using self we can cache feed data and avoid redundant DB hits.

Static Factory Methods

class UserCreator {

  public static function create($name) {

    $user = new User();
    $user->name = $name;
    return $user;

  } 

}

$user = UserCreator::create("John"); 

Here self offers a clean interface to instantiate class objects indirectly.

The key takeaway is applying $this and self judiciously based on instance vs class context unlocks more versatile, structured code.

$this And Self In Other Languages

It‘s also instructive to contrast PHP‘s approach to other languages:

JavaScript

Similarly provides this and static keywords serving analogous instance and class accessor roles. Subtle binding differences exist around lexical scope and invocation context.

Java

Only employs this for instance access but relies on direct class names, e.g. MyClass.staticCounter, for static access rather than a self equivalent. Signatures are also strongly typed.

Python

Adopts a self parameter convention to provide instance access rather than a dedicated keyword. Mainly focuses on instance member access with classes having relatively simple static namespacing.

PHP strikes a nice balance between flexibility and structure – delegating specialized functionality to both $this and self interoperably.

Optimizing With $this And Self

As a senior engineer and architect, properly harnessing $this and self has allowed me to achieve major performance gains across applications.

Some optimization best practices include:

Singleton Pattern

class Config {

  private static $instance;

  private function __construct() { }

  public static function instance() {

    if (!self::$instance) {
      self::$instance = new self();
    }

    return self::$instance;

  }

}

Here using self lets us implement a singleton that initializes only once for heavy reusable objects like databases.

Value Object Caching

class Size {

  private static $cache = []; 

  private $width;
  private $height;

  private function __construct() {

    // Calculate expensive dimensions 

  }

  public static function fromDimensions($w, $h) {

    $key = "{$w}-{$h}";

    if (!isset(self::$cache[$key])) {

      self::$cache[$key] = new self($w, $h);

    }

    return self::$cache[$key];

  }

}

By caching instances via self we can optimize creating duplicate immutable objects.

Leveraging $this and self properly allows you to write more efficient, performant object-oriented PHP.

When To Use Each Keyword

To recap, here is a comparison of when $this vs self are applicable:

$this self
Used within non-static methods Used within static methods
Refers to the current instance Refers to the current class
Grants access to non-static members Grants access to static members

Or stated simply:

  • When accessing instance members from an object, use $this
  • When accessing static members from a class itself, use self

Key Takeaways

As leading enterprises including Mailchimp, Slack, and Etsy demonstrate, wielding object-oriented PHP effectively unlocks scalability.

Mastering the nuances of foundational keywords like $this and self paves that path to success by promoting:

  • Inheritance – Adheres to OOP principles allowing extensible behavior
  • Organization – Structures code by properly scoping instance vs class
  • Optimization – Facilitates patterns like singletons and caching
  • Readability – Makes intentions clear when accessing members

Understanding each one‘s purpose gets you on the fast track to leveraging advanced object-oriented techniques.

So remember to keep your $this and self straight – your future self will thank you!

References

[[1]] CaptDrew. www.monkeh.works, 2021 https://www.monkeh.works/blog/view/$this-vs-self-in-php

[[2]] Valdez, Ferdinand. www.tutswerk.com, 2022
https://tutswerk.com/understanding-this-vs-self-in-php

Similar Posts