When should I use 'self' over '$this'?
Solution 1:
Short Answer
Use
$this
to refer to the current object. Useself
to refer to the current class. In other words, use$this->member
for non-static members, useself::$member
for static members.
Full Answer
Here is an example of correct usage of $this
and self
for non-static and static member variables:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}
new X();
?>
Here is an example of incorrect usage of $this
and self
for non-static and static member variables:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo self::$non_static_member . ' '
. $this->static_member;
}
}
new X();
?>
Here is an example of polymorphism with $this
for member functions:
<?php
class X {
function foo() {
echo 'X::foo()';
}
function bar() {
$this->foo();
}
}
class Y extends X {
function foo() {
echo 'Y::foo()';
}
}
$x = new Y();
$x->bar();
?>
Here is an example of suppressing polymorphic behaviour by using self
for member functions:
<?php
class X {
function foo() {
echo 'X::foo()';
}
function bar() {
self::foo();
}
}
class Y extends X {
function foo() {
echo 'Y::foo()';
}
}
$x = new Y();
$x->bar();
?>
The idea is that
$this->foo()
calls thefoo()
member function of whatever is the exact type of the current object. If the object is oftype X
, it thus callsX::foo()
. If the object is oftype Y
, it callsY::foo()
. But with self::foo(),X::foo()
is always called.
From http://www.phpbuilder.com/board/showthread.php?t=10354489:
By http://board.phpbuilder.com/member.php?145249-laserlight
Solution 2:
The keyword self does NOT refer merely to the 'current class', at least not in a way that restricts you to static members. Within the context of a non-static member, self
also provides a way of bypassing the vtable (see wiki on vtable) for the current object. Just as you can use parent::methodName()
to call the parents version of a function, so you can call self::methodName()
to call the current classes implementation of a method.
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getTitle() {
return $this->getName()." the person";
}
public function sayHello() {
echo "Hello, I'm ".$this->getTitle()."<br/>";
}
public function sayGoodbye() {
echo "Goodbye from ".self::getTitle()."<br/>";
}
}
class Geek extends Person {
public function __construct($name) {
parent::__construct($name);
}
public function getTitle() {
return $this->getName()." the geek";
}
}
$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();
This will output:
Hello, I'm Ludwig the geek
Goodbye from Ludwig the person
sayHello()
uses the $this
pointer, so the vtable is invoked to call Geek::getTitle()
.
sayGoodbye()
uses self::getTitle()
, so the vtable is not used, and Person::getTitle()
is called. In both cases, we are dealing with the method of an instantiated object, and have access to the $this
pointer within the called functions.
Solution 3:
Do not use self::
. Use static::
*
There is another aspect of self:: that is worth mentioning. Annoyingly, self::
refers to the scope at the point of definition, not at the point of execution. Consider this simple class with two methods:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
If we call Person::status()
we will see "Person is alive" . Now consider what happens when we make a class that inherits from this:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Calling Deceased::status()
we would expect to see "Person is deceased". However, we see "Person is alive" as the scope contains the original method definition when the call to self::getStatus()
was defined.
PHP 5.3 has a solution. The static::
resolution operator implements "late static binding" which is a fancy way of saying that it's bound to the scope of the class called. Change the line in status()
to static::getStatus()
and the results are what you would expect. In older versions of PHP you will have to find a kludge to do this.
See PHP Documentation
So to answer the question not as asked...
$this->
refers to the current object (an instance of a class), whereas static::
refers to a class.
Solution 4:
To really understand what we're talking about when we talk about self
versus $this
, we need to actually dig into what's going on at a conceptual and a practical level. I don't really feel any of the answers do this appropriately, so here's my attempt.
Let's start off by talking about what a class and an object is.
Classes And Objects, Conceptually
So, what is a class? A lot of people define it as a blueprint or a template for an object. In fact, you can read more About Classes In PHP Here. And to some extent that's what it really is. Let's look at a class:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
As you can tell, there is a property on that class called $name
and a method (function) called sayHello()
.
It's very important to note that the class is a static structure. Which means that the class Person
, once defined, is always the same everywhere you look at it.
An object on the other hand is what's called an instance of a Class. What that means is that we take the "blueprint" of the class, and use it to make a dynamic copy. This copy is now specifically tied to the variable it's stored in. Therefore, any changes to an instance is local to that instance.
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
We create new instances of a class using the new
operator.
Therefore, we say that a Class is a global structure, and an Object is a local structure. Don't worry about that funny ->
syntax, we're going to go into that in a little bit.
One other thing we should talk about, is that we can check if an instance is an instanceof
a particular class: $bob instanceof Person
which returns a boolean if the $bob
instance was made using the Person
class, or a child of Person
.
Defining State
So let's dig a bit into what a class actually contains. There are 5 types of "things" that a class contains:
-
Properties - Think of these as variables that each instance will contain.
class Foo { public $bar = 1; }
-
Static Properties - Think of these as variables that are shared at the class level. Meaning that they are never copied by each instance.
class Foo { public static $bar = 1; }
-
Methods - These are functions which each instance will contain (and operate on instances).
class Foo { public function bar() {} }
-
Static Methods - These are functions which are shared across the entire class. They do not operate on instances, but instead on the static properties only.
class Foo { public static function bar() {} }
-
Constants - Class resolved constants. Not going any deeper here, but adding for completeness:
class Foo { const BAR = 1; }
So basically, we're storing information on the class and object container using "hints" about static which identify whether the information is shared (and hence static) or not (and hence dynamic).
State and Methods
Inside of a method, an object's instance is represented by the $this
variable. The current state of that object is there, and mutating (changing) any property will result in a change to that instance (but not others).
If a method is called statically, the $this
variable is not defined. This is because there's no instance associated with a static call.
The interesting thing here is how static calls are made. So let's talk about how we access the state:
Accessing State
So now that we have stored that state, we need to access it. This can get a bit tricky (or way more than a bit), so let's split this into two viewpoints: from outside of an instance/class (say from a normal function call, or from the global scope), and inside of an instance/class (from within a method on the object).
From Outside Of An Instance/Class
From the outside of an instance/class, our rules are quite simple and predictable. We have two operators, and each tells us immediately if we're dealing with an instance or a class static:
-
->
- object-operator - This is always used when we're accessing an instance.$bob = new Person; echo $bob->name;
It's important to note that calling
Person->foo
does not make sense (sincePerson
is a class, not an instance). Therefore, that is a parse error. -
::
- scope-resolution-operator - This is always used to access a Class static property or method.echo Foo::bar()
Additionally, we can call a static method on an object in the same way:
echo $foo::bar()
It's extremely important to note that when we do this from outside, the object's instance is hidden from the
bar()
method. Meaning that it's the exact same as running:$class = get_class($foo); $class::bar();
Therefore, $this
is not defined in the static call.
From Inside Of An Instance/Class
Things change a bit here. The same operators are used, but their meaning becomes significantly blurred.
The object-operator ->
is still used to make calls to the object's instance state.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Calling the bar()
method on $foo
(an instance of Foo
) using the object-operator: $foo->bar()
will result in the instance's version of $a
.
So that's how we expect.
The meaning of the ::
operator though changes. It depends on the context of the call to the current function:
-
Within a static context
Within a static context, any calls made using
::
will also be static. Let's look at an example:class Foo { public function bar() { return Foo::baz(); } public function baz() { return isset($this); } }
Calling
Foo::bar()
will call thebaz()
method statically, and hence$this
will not be populated. It's worth noting that in recent versions of PHP (5.3+) this will trigger anE_STRICT
error, because we're calling non-static methods statically. -
Within an instance context
Within an instance context on the other hand, calls made using
::
depend on the receiver of the call (the method we're calling). If the method is defined asstatic
, then it will use a static call. If it's not, it will forward the instance information.So, looking at the above code, calling
$foo->bar()
will returntrue
, since the "static" call happens inside of an instance context.
Make sense? Didn't think so. It's confusing.
Short-Cut Keywords
Because tying everything together using class names is rather dirty, PHP provides 3 basic "shortcut" keywords to make scope resolving easier.
self
- This refers to the current class name. Soself::baz()
is the same asFoo::baz()
within theFoo
class (any method on it).parent
- This refers to the parent of the current class.static
- This refers to the called class. Thanks to inheritance, child classes can override methods and static properties. So calling them usingstatic
instead of a class name allows us to resolve where the call came from, rather than the current level.
Examples
The easiest way to understand this is to start looking at some examples. Let's pick a class:
class Person {
public static $number = 0;
public $id = 0;
public function __construct() {
self::$number++;
$this->id = self::$number;
}
public $name = "";
public function getName() {
return $this->name;
}
public function getId() {
return $this->id;
}
}
class Child extends Person {
public $age = 0;
public function __construct($age) {
$this->age = $age;
parent::__construct();
}
public function getName() {
return 'child: ' . parent::getName();
}
}
Now, we're also looking at inheritance here. Ignore for a moment that this is a bad object model, but let's look at what happens when we play with this:
$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3
So the ID counter is shared across both instances and the children (because we're using self
to access it. If we used static
, we could override it in a child class).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Note that we're executing the Person::getName()
instance method every time. But we're using the parent::getName()
to do it in one of the cases (the child case). This is what makes this approach powerful.
Word Of Caution #1
Note that the calling context is what determines if an instance is used. Therefore:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Is not always true.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Now it is really weird here. We're calling a different class, but the $this
that gets passed to the Foo::isFoo()
method is the instance of $bar
.
This can cause all sorts of bugs and conceptual WTF-ery. So I'd highly suggest avoiding the ::
operator from within instance methods on anything except those three virtual "short-cut" keywords (static
, self
, and parent
).
Word Of Caution #2
Note that static methods and properties are shared by everyone. That makes them basically global variables. With all the same problems that come with globals. So I would be really hesitant to store information in static methods/properties unless you're comfortable with it being truly global.
Word Of Caution #3
In general you'll want to use what's known as Late-Static-Binding by using static
instead of self
. But note that they are not the same thing, so saying "always use static
instead of self
is really short-sighted. Instead, stop and think about the call you want to make and think if you want child classes to be able to override that static resolved call.
TL/DR
Too bad, go back and read it. It may be too long, but it's that long because this is a complex topic
TL/DR #2
Ok, fine. In short, self
is used to reference the current class name within a class, where as $this
refers to the current object instance. Note that self
is a copy/paste short-cut. You can safely replace it with your class name, and it'll work fine. But $this
is a dynamic variable that can't be determined ahead of time (and may not even be your class).
TL/DR #3
If the object-operator is used (->
), then you always know you're dealing with an instance. If the scope-resolution-operator is used (::
), you need more information about the context (are we in an object-context already? Are we outside of an object? etc).
Solution 5:
self
(not $self) refers to the type of class, whereas $this
refers to the current instance of the class. self
is for use in static member functions to allow you to access static member variables. $this
is used in non-static member functions, and is a reference to the instance of the class on which the member function was called.
Because this
is an object, you use it like: $this->member
Because self
is not an object, it's basically a type that automatically refers to the current class. You use it like: self::member