$this vs parent vs self vs static

Erland Muchasaj
5 min readMay 12, 2023

--

this, self, static, parent
Differences between $this, parent, self, and static

A long time ago, a colleague asked me: “What is the difference between self and static?”.

And man o man, I had used them and still couldn’t answer. Then I research and learn it. Then I forget it again. Then I search for it again and forgot it again, and so on.

So I decided to write an article to tackle the main keywords.

In our previous article we talked about $this, what is it, and how it can be used.
In this article, we will talk about the parent 🥸, self and static.

  1. self: The self keyword refers to the current class itself. It is used to access static properties, constants, and methods within the same class. When using self, the class in which the keyword is written does not change, regardless of the context or inheritance.
  2. static: The static keyword behaves similarly to self, but with one crucial difference. It represents the class in which it is called, rather than the class in which it is written. This allows for late static binding, enabling late-bound method calls and property access.
  3. parent: The parent keyword is used to access members of the parent class within a child class. It is primarily used to invoke overridden methods or access overridden properties from the parent class.
  4. $this: The $this keyword refers to the current instance of the class. It is primarily used to access non-static properties and invoke non-static methods within the class. For more details, you can reference this article.

Let me give you some examples:

Example: #1

class ParentClass
{
protected string $message = "Hello ParentClass";

public function greet(): string
{
return $this->message;
}
}

class ChildClass extends ParentClass
{
}


$child = new ChildClass();
echo $child->greet(); // Outputs "Hello ParentClass"

Example: #2

class ParentClass
{
protected string $message = "Hello ParentClass";

public function greet(): string
{
return $this->message;
}
}

class ChildClass extends ParentClass
{
protected string $message = "Hello ChildClass";
}

$child = new ChildClass();
echo $child->greet(); // Outputs "Hello ChildClass"

Example: #3

class ParentClass
{
protected string $message = "Hello ParentClass";

public function greet(): string
{
return $this->message;
}
}

class ChildClass extends ParentClass
{
protected string $message = "Hello ChildClass";

public function greet(): string
{
return $this->message . ', ' . parent::greet();
}
}

$child = new ChildClass();
echo $child->greet(); // Outputs "Hello ChildClass, Hello ChildClass"

Example: #4

class ChildClass extends ParentClass
{
public function greet(): string
{
return $this->message . ' ' . parent::greet();
}
}

$child = new ChildClass();
echo $child->greet(); // Outputs "Hello ParentClass, Hello ParentClass"

NOTE: You can not access the parent method from the child method using $this, because this would result in an infinite loop and throw an error.

Example: #5

class ChildClass extends ParentClass
{
public function greet(): void
{
return $this->message . ' ' . $this->greet();
}
}

$child = new ChildClass();
echo $child->greet();

// Xdebug has detected a possible infinite loop,
// and aborted your script with a stack depth of '256' frames

NOTE: You can not access non-static properties/variables using the parent keywords, but you can only access static properties of the parent class.

Now let's look a little deeper between self and static

Now as you know in Laravel, we have models that extend a base Model. And by default, all models use the same connection, but we can also overwrite the connection in whichever model we want.
Now let’s imagine that we have a Model class that has a static connection property and a connect() method.
We'll also imagine that we have a User class and a Post class that inherits the Model class and overrides the connection property.

The classes may look something like this:

class Model
{
public static string $connection = "mysql::Model";

public static function connect(): string
{
return 'Making connection to: '. self::$connection;
}
}

class User extends Model
{
public static string $connection = "postgres::User";
}

class Post extends Model
{
public static string $connection = "redis::Post";
}

To call a static method we use the scope resolution operator (:: aka the double colon).

Model::connect();// Outputs "Making connection to: mysql::Model"
User::connect(); // Outputs "Making connection to: mysql::Model"
Post::connect(); // Outputs "Making connection to: mysql::Model"

As you can see now the self uses the property in the class where the method being called exists.

In all cases, the connect method is on the Model class because one doesn't exist on the User class or on the Post class, so the self now refers to the methods and properties of the Model class.

Another way that we can access the User or Post class $connection property is by overwriting the connect() method.

class Model
{
public static string $connection = "mysql::Model";

public static function connect(): string
{
return 'Making connection to: '. self::$connection;
}
}

class User extends Model
{
public static string $connection = "postgres::User";

public static function connect(): string
{
return 'Making connection to: '. self::$connection;
}
}

class Post extends Model
{
public static string $connection = "redis::Post";

public static function connect(): string
{
return 'Making connection to: '. self::$connection;
}
}

And the result would be:

Model::connect();// Outputs "Making connection to: mysql::Model"
User::connect(); // Outputs "Making connection to: postgres::User"
Post::connect(); // Outputs "Making connection to: redis::Post"

As you can see, now the call to connect() uses the $connection field on the User and Post class because that's where the method exists.

We can achieve the same result using the static keyword. By just making a small change to the connect() method of the Model class, changing self to static.

change self to static

Now calling the method connect() on all 3 classes the result would be as follows:

Model::connect();// Outputs "Making connection to: mysql::Model"
User::connect(); // Outputs "Making connection to: postgres::User"
Post::connect(); // Outputs "Making connection to: redis::Post"

When to use which?

This boils down to what you wanna do, the choice between using self:: or static:: depends on the specific context and requirements of your code.

Use self:: when:

  1. You want to refer to a static property or call a static method within the same class where the self:: reference is used.
  2. You want to ensure that the reference remains bound to the current class, regardless of any subclassing or overriding.

Use static:: when:

  1. You want to refer to a static property or call a static method within a class hierarchy, considering potential subclassing and overriding.
  2. You want the reference to dynamically bind to the class that called the method, allowing for late static binding.

Feel free to Subscribe for more content like this 🔔, clap 👏🏻 , comment 💬 and share the article with anyone you’d like

And as it always has been, I appreciate your support, and thanks for reading.

--

--