> ## Content Index
> Fetch the complete content index at: https://madewithlove.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# PHP type hints: self and parent
- URL: https://madewithlove.com/blog/self-and-parent-type-hints/
- Published: 2015-03-14T16:11:00.000Z
- Updated: 2026-05-29T11:58:57.000Z
- Author: Hannes Van De Vreken
- Tags: Engineering, Tutorials

In PHP we can type hint function arguments since version 5.0\. Over the years and with newer versions of PHP the number of possible type hints have increased. Here’s an overview:

```
public function foo(
    // Since 5.0
    self $self,
    parent $parent,
    FooInterface $foo,
    // Since 5.1
    array $array,
    // Since 5.4
    callable $callable,
    // Since 7.0
    bool $bool,
    float $float,
    int $int,
    string $string
) {
    ...
}
```

Since PHP 5.0 we’ve been able to [type hint function arguments](http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration) and since PHP 7.0 we’re aso able to type hint scalar values. The entire set of type hints can be used for [function return type hinting](http://php.net/manual/en/functions.returning-values.php#functions.returning-values.type-declaration) since version 7.0 as well. Let’s take a closer look at `self` and `parent`. They’ve been around for a long time  
but we don’t see them very often. Why is that?

## self

Self means: an object of the same type (the current class or a subclass). Every variable passed must be an `instanceof` the same class.

### Function argument type

```
<code class="language-php">&lt;?php

interface Person {
    public function addSibling(self $sibling)
    {
        // ...
    }
}</code>
```

When modelling relations between nodes/objects/…, it happens that a relationship needs to be modelled between two objects of the same type. In this case it’s useful to use the `self` type hint.

When you create an implementation of this interface (or when overwriting this in case of less SOLID designed code) it will be necessary to replace the `self` type hint with the original class/interface name.

```
<code class="language-php">&lt;?php

use Person as PersonContract;

class Person implements PersonContract {
    public function addSibling(PersonContract $sibling)
    {
        // ...
    }
}</code>
```

In the example above, if `setBaz` is not a method of the interface `Foo`, it will not be recognized by the IDE. Thus for chaining methods, the return type `self` isn’t so useful.

### Return type

Let’s take a look in what situations we can use

### Mutators

One of the more obvious use case is setters (or mutators) that allow method chaining.

```
<code class="language-php">&lt;?php

$foo-&gt;setBar($bar)-&gt;setBaz($baz);</code>
```

If you use `self` return type it doesn’t matter if the method returns a cloned version of the object (this is the case when you’re dealing with immutable objects). The object that is returned is of the same type as the object on which the method is called.

```
<code class="language-php">&lt;?php

interface Foo {
    /**
     * @param Bar $bar
     * @return self
     */
    public function setBar(Bar $bar) : self;
}</code>
```

When extending or implementing a method in a subclass you have to make type hint explicit so that declaration is compatible.

```
<code class="language-php">&lt;?php

use Foo as FooContract;

class Foo implements FooContract
{
    /**
     * {@inheritdoc}
     */
    public function setBar(Bar $bar) : FooContract
    {
        // ...
        return $this;
    }
}</code>
```

If you use this object it will tell your IDE that whatever is returned will be of type `Foo` (the interface). So practically it won’t/shouldn’t autocomplete method names of the Foo implementing class anymore.

```
<code class="language-php">&lt;?php

/* @var Foo $foo */
$foo-&gt;setBar(new Bar())-&gt;setBaz(new Baz());</code>
```

Prior to PHP 7.0 we usually only declared return types in the docblocks with `@return $this`, `@return self` or `@return static`.  
For chained methods I still use `@return static` and `@return $this` in the docblocks.

### Factory methods

It’s not easy to come up with examples of non-setter methods that still return objects of the same class. Here’s one:

```
<code class="language-php">&lt;?php

interface Foo
{
    public function wrapWithLogDecorator(PsrLogLoggerInterface $logger) : self;
}</code>
```

An implementation would be:

```
<code class="language-php">&lt;?php

trait LoggerWrapping
{
    public function wrapWithLogDecorator(PsrLogLoggerInterface $logger) : Foo
    {
         return new LogWrapper($this);
    }
}</code>
```

I’m not saying this is good design, though. This method clearly doesn’t belong in this interface. There are better factory-like methods that can have a `self` return type hint. I just can’t come up with a practical one at this moment. Feel free to suggest an example in the comments below.

## parent

I noticed from the PHP docs that `parent` is a valid type hint. Let me explain what `parent` means in the context of type hinting:

```
<code class="language-php">&lt;?php

class Foo extends Bar {
    public function setBar(parent $bar)
    {
        // ...
    }
}</code>
```

`parent` always refers to the class that you are extending. Thus in the example above it means: Bar, or one of its subclasses. The object that gets passed here could be of a sibling class of Foo, for example.

The type hint can not refer to an interface. It’s exactly the same as when you would call a method on a parent class (`parent::__construct` for example). You can only use that when the current class actually extends a parent class.

There are a couple of reasons why the `parent` type hint isn’t used much:

When your code’s design respects the SOLID principles, it should strike you that almost everything is either an interface or an implementing class (leaf node in inheritance tree). You’ll see that the number of abstract classes will be very small and almost no classes get extended. So using the `parent` type hint is not that useful, except in some very rare cases.

Secondly, it is generally better to type hint interfaces. This again is part of the SOLID design principles: Liskov Substitution Principle (objects should be replaceable with objects of subtypes), Interface Segregation Principle and Dependency Inversion Principle (Depend upon abstractions(interfaces)). Thus, again: the amount of type hints that are class type hints and not interface type hints is very small.

If you’re having questions or would like to add something, feel free to leave a comment below.

Cheers!

## Other interesting reads:

- [The easiest production-ready image to run your Laravel application](https://madewithlove.com/blog/the-easiest-production-ready-image-to-run-your-laravel-application/)
- [A few things you should know to nail your next job interview](https://madewithlove.com/blog/a-few-things-you-should-know-to-nail-your-next-job-interview/)
- [How to assist your product marketing team as a software engineer](https://madewithlove.com/blog/how-to-assist-your-product-marketing-team-as-a-software-engineer/)

In PHP we can type hint function arguments since version 5.0\. Over the years and with newer versions of PHP the number of possible type hints have increased. Here’s an overview:

```php
<?php

public function foo(
    // Since 5.0
    self $self,
    parent $parent,
    FooInterface $foo,
    // Since 5.1
    array $array,
    // Since 5.4
    callable $callable,
    // Since 7.0
    bool $bool,
    float $float,
    int $int,
    string $string
) {
    ...
}
```

Since PHP 5.0 we’ve been able to [type hint function arguments](http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration) and since PHP 7.0 we’re aso able to type hint scalar values. The entire set of type hints can be used for [function return type hinting](http://php.net/manual/en/functions.returning-values.php#functions.returning-values.type-declaration) since version 7.0 as well. Let’s take a closer look at `self` and `parent`. They’ve been around for a long time  
but we don’t see them very often. Why is that?

## self

Self means: an object of the same type (the current class or a subclass). Every variable passed must be an `instanceof` the same class.

### Function argument type

```php
<?php

interface Person {
    public function addSibling(self $sibling)
    {
        // ...
    }
}
```

When modelling relations between nodes/objects/…, it happens that a relationship needs to be modelled between two objects of the same type. In this case it’s useful to use the `self` type hint.

When you create an implementation of this interface (or when overwriting this in case of less SOLID designed code) it will be necessary to replace the `self` type hint with the original class/interface name.

```php
<?php

use Person as PersonContract;

class Person implements PersonContract {
    public function addSibling(PersonContract $sibling)
    {
        // ...
    }
}
```

### Return type

Let’s take a look in what situations we can use `self` as a return type.

### Mutators

One of the more obvious use case is setters (or mutators) that allow method chaining.

```php
<?php

$foo->setBar($bar)->setBaz($baz);
```

If you use `self` return type it doesn’t matter if the method returns a cloned version of the object (this is the case when you’re dealing with immutable objects). The object that is returned is of the same type as the object on which the method is called.

```php
<?php

interface Foo {
    /**
     * @param Bar $bar
     * @return self
     */
    public function setBar(Bar $bar) : self;
}
```

When extending or implementing a method in a subclass you have to make type hint explicit so that declaration is compatible.

```php
<?php

use Foo as FooContract;

class Foo implements FooContract
{
    /**
     * {@inheritdoc}
     */
    public function setBar(Bar $bar) : FooContract
    {
        // ...
        return $this;
    }
}
```

If you use this object it will tell your IDE that whatever is returned will be of type `Foo` (the interface). So practically it won’t/shouldn’t autocomplete method names of the Foo implementing class anymore.

```php
<?php

/* @var Foo $foo */
$foo->setBar(new Bar())->setBaz(new Baz());
```

In the example above, if `setBaz` is not a method of the interface `Foo`, it will not be recognized by the IDE. Thus for chaining methods, the return type `self` isn’t so useful.

Prior to PHP 7.0 we usually only declared return types in the docblocks with `@return $this`, `@return self` or `@return static`.  
For chained methods I still use `@return static` and `@return $this` in the docblocks.

### Factory methods

It’s not easy to come up with examples of non-setter methods that still return objects of the same class. Here’s one:

```php
<?php

interface Foo
{
    public function wrapWithLogDecorator(PsrLogLoggerInterface $logger) : self;
}
```

An implementation would be:

```php
<?php

trait LoggerWrapping
{
    public function wrapWithLogDecorator(PsrLogLoggerInterface $logger) : Foo
    {
         return new LogWrapper($this);
    }
}
```

I’m not saying this is good design, though. This method clearly doesn’t belong in this interface. There are better factory-like methods that can have a `self` return type hint. I just can’t come up with a practical one at this moment. Feel free to suggest an example in the comments below.

## parent

I noticed from the PHP docs that `parent` is a valid type hint. Let me explain what `parent` means in the context of type hinting:

```php
<?php

class Foo extends Bar {
    public function setBar(parent $bar)
    {
        // ...
    }
}
```

`parent` always refers to the class that you are extending. Thus in the example above it means: Bar, or one of its subclasses. The object that gets passed here could be of a sibling class of Foo, for example.

The type hint can not refer to an interface. It’s exactly the same as when you would call a method on a parent class (`parent::__construct` for example). You can only use that when the current class actually extends a parent class.

There are a couple of reasons why the `parent` type hint isn’t used much:

When your code’s design respects the SOLID principles, it should strike you that almost everything is either an interface or an implementing class (leaf node in inheritance tree). You’ll see that the number of abstract classes will be very small and almost no classes get extended. So using the `parent` type hint is not that useful, except in some very rare cases.

Secondly, it is generally better to type hint interfaces. This again is part of the SOLID design principles: Liskov Substitution Principle (objects should be replaceable with objects of subtypes), Interface Segregation Principle and Dependency Inversion Principle (Depend upon abstractions(interfaces)). Thus, again: the amount of type hints that are class type hints and not interface type hints is very small.

If you’re having questions or would like to add something, feel free to leave a comment below.

Cheers!

## Other interesting reads:

- [The easiest production-ready image to run your Laravel application](https://madewithlove.com/blog/the-easiest-production-ready-image-to-run-your-laravel-application/)
- [A few things you should know to nail your next job interview](https://madewithlove.com/blog/a-few-things-you-should-know-to-nail-your-next-job-interview/)
- [How to assist your product marketing team as a software engineer](https://madewithlove.com/blog/how-to-assist-your-product-marketing-team-as-a-software-engineer/)