When should I use 'self' over '$this'?

Viewed 793790

In PHP 5, what is the difference between using self and $this?

When is each appropriate?

23 Answers

Short Answer

Use $this to refer to the current object. Use self to refer to the current class. In other words, use $this->member for non-static members, use self::$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 the foo() member function of whatever is the exact type of the current object. If the object is of type X, it thus calls X::foo(). If the object is of type Y, it calls Y::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

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.

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

$this-> is used to refer to a specific instance of a class's variables (member variables) or methods.

Example: 
$derek = new Person();

$derek is now a specific instance of Person. Every Person has a first_name and a last_name, but $derek has a specific first_name and last_name (Derek Martin). Inside the $derek instance, we can refer to those as $this->first_name and $this->last_name

ClassName:: is used to refer to that type of class, and its static variables, static methods. If it helps, you can mentally replace the word "static" with "shared". Because they are shared, they cannot refer to $this, which refers to a specific instance (not shared). Static Variables (i.e. static $db_connection) can be shared among all instances of a type of object. For example, all database objects share a single connection (static $connection).

Static Variables Example: Pretend we have a database class with a single member variable: static $num_connections; Now, put this in the constructor:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

Just as objects have constructors, they also have destructors, which are executed when the object dies or is unset:

function __destruct()
{
    $num_connections--;
}

Every time we create a new instance, it will increase our connection counter by one. Every time we destroy or stop using an instance, it will decrease the connection counter by one. In this way, we can monitor the number of instances of the database object we have in use with:

echo DB::num_connections;

Because $num_connections is static (shared), it will reflect the total number of active database objects. You may have seen this technique used to share database connections among all instances of a database class. This is done because creating the database connection takes a long time, so it's best to create just one, and share it (this is called a Singleton Pattern).

Static Methods (i.e. public static View::format_phone_number($digits)) can be used WITHOUT first instantiating one of those objects (i.e. They do not internally refer to $this).

Static Method Example:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

As you can see, public static function prettyName knows nothing about the object. It's just working with the parameters you pass in, like a normal function that's not part of an object. Why bother, then, if we could just have it not as part of the object?

  1. First, attaching functions to objects helps you keep things organized, so you know where to find them.
  2. Second, it prevents naming conflicts. In a big project, you're likely to have two developers create getName() functions. If one creates a ClassName1::getName(), and the other creates ClassName2::getName(), it's no problem at all. No conflict. Yay static methods!

SELF:: If you are coding outside the object that has the static method you want to refer to, you must call it using the object's name View::format_phone_number($phone_number); If you are coding inside the object that has the static method you want to refer to, you can either use the object's name View::format_phone_number($pn), OR you can use the self::format_phone_number($pn) shortcut

The same goes for static variables: Example: View::templates_path versus self::templates_path

Inside the DB class, if we were referring to a static method of some other object, we would use the object's name: Example: Session::getUsersOnline();

But if the DB class wanted to refer to its own static variable, it would just say self: Example: self::connection;

Hope that helps clear things up :)

According to Static Keyword, there isn't any $self. There is only $this, for referring to the current instance of the class (the object), and self, which can be used to refer to static members of a class. The difference between an object instance and a class comes into play here.

I believe the question was not whether you can call the static member of the class by calling ClassName::staticMember. The question was what's the difference between using self::classmember and $this->classmember.

For example, both of the following examples work without any errors, whether you use self:: or $this->

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}

I ran into the same question and the simple answer was:

  • $this requires an instance of the class
  • self:: doesn't

Whenever you are using static methods or static attributes and want to call them without having an object of the class instantiated, you need to use self: to call them, because $this always requires an object to be created.

self:: A keyword used for the current class and basically it is used to access static members, methods, and constants. But in case of $this, you cannot call the static member, method, and functions.

You can use the self:: keyword in another class and access the static members, method, and constants. When it will be extended from the parent class and the same in case of the $this keyword. You can access the non-static members, method and function in another class when it will be extended from the parent class.

The code given below is an example of the self:: and $this keywords. Just copy and paste the code in your code file and see the output.

class cars{
    var $doors = 4;
    static $car_wheel = 4;

    public function car_features(){
        echo $this->doors . " Doors <br>";
        echo self::$car_wheel . " Wheels <br>";
    }
}

class spec extends cars{
    function car_spec(){
        print(self::$car_wheel . " Doors <br>");
        print($this->doors . " Wheels <br>");
    }
}

/********Parent class output*********/

$car = new cars;
print_r($car->car_features());

echo "------------------------<br>";

/********Extend class from another class output**********/


$car_spec_show = new spec;

print($car_spec_show->car_spec());
Related