PHP: When do you use self and when $this?
Inside a PHP class there are two ways to reach your own class: with $this->
and with self::. The basic rule is quickly explained. It gets interesting with
the third keyword, which most people overlook.
The basic rule
$this-> refers to the instance, self:: to the class:
<?php
class Config {
public const VERSION = '1.0'; // belongs to the class
public static int $counter = 0; // belongs to the class
public string $name = 'instance'; // belongs to the instance
public function show(): void {
echo self::VERSION; // constant -> self::
echo self::$counter; // static -> self::
echo $this->name; // instance -> $this->
}
}
?>
A way to remember it: does the thing exist even when no object has been created
yet? Then self::. Does it exist per object? Then $this->.
The difference is easy to show. Static properties are shared by all instances, instance properties are not:
Config::$counter via $a: 5, via $b: 5
$a->name: A, $b->name: B
$this does not exist in static methods
Obvious, but you get to know the error message sooner or later anyway:
<?php
class Test {
public int $value = 42;
public static function staticMethod(): string {
return (string) $this->value; // does not work
}
}
?>
The result:
Error: Using $this when not in object context
Note that this is an Error and not a warning. Your script therefore aborts at
that point unless you catch it.
And now the part that actually matters: static
Besides self:: there is also static::. The difference only becomes apparent
once you derive from a class — and then it becomes apparent all the more
clearly.
selfis bound to the class the line is written in.staticis bound to the class the call was made through.
This is called late static binding and has existed since PHP 5.3. An example:
<?php
class Base {
public static function withSelf(): object { return new self(); }
public static function withStatic(): object { return new static(); }
}
class Derived extends Base {}
?>
And this is what comes out:
Derived::withSelf() gives Base
Derived::withStatic() gives Derived
That is the classic case: you write a factory method in a base class, derive
from it, and still always get objects of the base class. The mistake is
new self() instead of new static().
The same happens with overridden static methods:
<?php
class Parents {
public static function name(): string { return 'Parent'; }
public static function viaSelf(): string { return self::name(); }
public static function viaStatic(): string { return static::name(); }
}
class Child extends Parents {
public static function name(): string { return 'Child'; }
}
?>
Child::viaSelf() => Parent
Child::viaStatic() => Child
So self::name() calls the base class’s method, even though Child has
overridden it.
Constants are affected too
This case gets mentioned less often, but occurs just as frequently in practice. Constants in a base class are a widespread configuration pattern:
<?php
class Config {
public const VERSION = '1.0';
public function show(): void {
echo self::VERSION;
echo static::VERSION;
}
}
class NewConfig extends Config {
public const VERSION = '2.0';
}
?>
For an object of class NewConfig:
self::VERSION => 1.0
static::VERSION => 2.0
self::VERSION returns the base class’s constant, even though the derived class
has overridden it. And because neither an error nor a warning occurs here, this
kind of thing often goes unnoticed for a long time.
Summary
$this->for everything that belongs to the instance.self::for constants, static properties and static methods.static::whenever derived classes should be able to override the behaviour.- When in doubt, use
new static()rather thannew self()in factory methods. $thisin a static method is anError, notnull.
About Netcup (advertisement)
The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).