In PHP 5, what is the difference between using self
and $this
?
When is each appropriate?
NOTE: This question was originally posted at StackOverflow.com by Casey Watson
- Vicki asked 16 years ago
- last edited 13 years ago
$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?
- First, attaching functions to objects helps you keep things organized, so you know where to find them.
- 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 🙂
NOTE: This answer was originally posted at StackOverflow.com by lo_fye
- Deborah answered 16 years ago
- last edited 9 years ago
- You must login to post comments
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 what we see is “Person is alive” as the scope contains the original method definition when 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 its 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.
http://php.net/manual/en/language.oop5.late-static-bindings.php
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
NOTE: This answer was originally posted at StackOverflow.com by Sqoo
- Jim answered 13 years ago
- last edited 12 years ago
-
What about for class constants?
NOTE: This comment was originally posted at StackOverflow.com by Kevin Bond
-
I guess the same goes
NOTE: This comment was originally posted at StackOverflow.com by Sqoo
-
There should be "Calling Deceased::status()..." not "Calling Deceased::getStatus()..."
NOTE: This comment was originally posted at StackOverflow.com by royas
-
Thanks for spotting that. Now fixed :)
NOTE: This comment was originally posted at StackOverflow.com by Sqoo
- You must login to post comments
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();
?>
NOTE: This answer was originally posted at StackOverflow.com by Mohit Bumb
- Jane answered 13 years ago
- You must login to post comments
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 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.
NOTE: This answer was originally posted at StackOverflow.com by nbeagle
- Christine answered 15 years ago
- last edited 13 years ago
-
very well explained, +1
NOTE: This comment was originally posted at StackOverflow.com by Daniel
- You must login to post comments
NOTE: This comment was originally posted at StackOverflow.com by Craig Hooghiem
NOTE: This comment was originally posted at StackOverflow.com by Shane