Jump to content

"this" Variable


kevint

Recommended Posts

To a lot of the people here, this is going to be a really stupid question.

 

I know this, because based on the amount of code I have seen that uses the technique in question, it must be quite prolific.

 

However, I have not been able to find a good explanation of the theory.

 

Question:

 

What exactly does the "this" variable (is it even a variable?) do, in PHP or any other language (such as JavaScript, where I see it even more frequently)?

 

For example, this bit of JavaScript from a tutorial I was checking out on IBM's dev site:

 

<select id="elFeedList" 
  onchange="loadFeed( this.options[this.selectedIndex].value )"> </select>

 

Or, more appropriately (since this is a PHP form), this code (from the same site):

 

private function __construct()
  {
    $dsn = 'mysql://root:password@localhost/rss';
    $this->_handle =& DB::Connect( $dsn, array() );
  }

 

I constantly see a variablish thing called $this in PHP code I check out, and I am not sure what exactly it does.  And I always see stuff like "this.something" in JS.

 

I haven't been able to find a good explanation.  Google returns plenty of pages that have the word "this" in them, but nothing dealing with what I am looking for.  Maybe I am searching wrong; there must be some kind of name for this feature.  I have no idea what it is though...

 

Help?

Link to comment
Share on other sites

$this is a reserved variable in most styles of code (originated from the programming language C) that returns the current class or object. 'this' is a reference to 'this object' or 'this scope'

 

Sometimes it's necessary to retrieve the value of $this from within an object.

This solution dedicates a public var $ID to store a unique identifier for the object:

 

<?php
class Someclass {
    public $ID;
   
    public function what_is_this() {
        return '$this is: ' . $this->get_varname();
    }
    private function get_varname() {
        $this->ID = uniqid();
        foreach($GLOBALS as $key => $val) {
            if (is_a($val,'Someclass')) {
                if ($val->ID === $this->ID) {
                    return $key;
                    break;
                }
            }
        }
    }
}

// example:
$my_var_instance = new Someclass;
echo $my_var_instance->what_is_this();   // returns '$this is: my_var_instance'
?>

In Visual BASIC style coding conventions, the variable is called 'me', and is referenced such as: 'me.title = 'Foobar'; '

Link to comment
Share on other sites

Actually, 'this' isn't in ANSI C, as the language has no concept of a class or object.

 

For the OP, 'this' is an instance variable.  It literally means the current instance of an existing class variable.  Example:

 

class ExampleClass
{
   private $name;
   private $age;

   public function __construct($name, $age)
   {
      $this->name = $name;
      $this->age = $age;
   }

   public function getName() { return $this->name; }
   public function getAge() { return $this->age; }
}

$person1 = new ExampleClass("Forrest Gump", 34);
$person2 = new ExampleClass("Lt. Dan", 39);

echo "Person1's name is " . $person1.getName();
echo "Person2's age is " . $person2.getAge();

 

As you can see, 'this' is contextual.  Its value depends on which instance of the class is being accessed.

Link to comment
Share on other sites

For the OP, 'this' is an instance variable.  It literally means the current instance of an existing class variable.

 

To be pedantic, 'this' is not an instance variable per say, but rather a pseudo-variable which in essence acts as a 'reference variable (or perhaps better phrased as an alias or object identifier) placeholder' which is 'the current instance of this class'. I think the term 'instance variable' is pretty much the object's properties.

 

According to the PHP manual: (via http://www.php.net/manual/en/language.oop5.basic.php)

The pseudo-variable $this is available when a method is called from within an object context. $this is a reference to the calling object ......

 

When we declare something like $person1 = new ExampleClass(); $person1 is not the actual object as we know (the actual object itself derives from new ExampleClass()), but rather a reference variable (object identifier) to that object. Obviously, when we're writing classes, we don't know what reference variables we're going to be using. So the pseudo-variable $this acts in their place.

 

Much like after we instantiate a class (create an object), we access its instance variable like say:

$person1->name  (where $person1 is the reference variable (a.k.a alias / object identifier) and 'name' is the instance variable), in a class, $this is the reference variable while 'name' is the instance variable.

Link to comment
Share on other sites

The info so far is very helpful!

 

And thank you also for the link to the manual.  I wasn't sure where to find it in there, and searching produced all kinds of results.

 

Just another question:

 

(Based on the code from Nightslyr):

 

class ExampleClass
{
   private $name;
   private $age;

   public function __construct($name, $age)
   {
      $this->name = $name;
      $this->age = $age;
   }

   public function getName() { return $this->name; }
   public function getAge() { return $this->age; }
}

 

Does the __construct() function always take care of assigning whatever variables are passed to a class when an instance of it is created?  What if I created a new ExampleClass, but passed it three values, like:

 

$blah = new ExampleClass("one",2,"thirdValue");

 

What would happen to the third value?  Since nothing deals with it in the __construct() function.  Also, how does the __construct() function know what $this->name is, so that it can assign it to private variable $name?  You pass two values to the class when you create a new instance of it, but how does it know that $this->name is the first value you pass, and $this->age is the second?

 

If I did pass it three values, how would I load the third value into a private variable called $third?

Link to comment
Share on other sites

The info so far is very helpful!

 

And thank you also for the link to the manual.  I wasn't sure where to find it in there, and searching produced all kinds of results.

 

Just another question:

 

(Based on the code from Nightslyr):

 

class ExampleClass
{
   private $name;
   private $age;

   public function __construct($name, $age)
   {
      $this->name = $name;
      $this->age = $age;
   }

   public function getName() { return $this->name; }
   public function getAge() { return $this->age; }
}

 

Does the __construct() function always take care of assigning whatever variables are passed to a class when an instance of it is created?  What if I created a new ExampleClass, but passed it three values, like:

 

$blah = new ExampleClass("one",2,"thirdValue");

 

What would happen to the third value?  Since nothing deals with it in the __construct() function.  Also, how does the __construct() function know what $this->name is, so that it can assign it to private variable $name?  You pass two values to the class when you create a new instance of it, but how does it know that $this->name is the first value you pass, and $this->age is the second?

 

If I did pass it three values, how would I load the third value into a private variable called $third?

 

I think you're getting the wrong idea of what's actually going on.

 

The constructor creates an object.  If you don't specify an explicit constructor, a default parameterless constructor is still invoked.  As far as I know, the order of how the arguments are passed to the constructor doesn't matter.  Constructors, in general, serve two purposes:

 

1. Actual object construction

2. Initial object initialization - that is, supplying initial values for its data members

 

In your question, using my example with the two properties, nothing would happen with the third argument passed into the constructor as the constructor itself doesn't have any code to handle a third argument.  In fact, you may get an error, since the constructor's signature only contains two parameters.  The best way to add another parameter to a class is to redefine the class itself, and code it into the definition.

 

The 'this' refers to the context of which object is currently being accessed, and nothing more.  It allows us to have many different instances of a class, all sharing the same structure (which is what the class provides) while having different values.  It's what allows us to have one class that can have derived objects represent both Forrest Gump and Lt. Dan.

Link to comment
Share on other sites

For the OP, 'this' is an instance variable.  It literally means the current instance of an existing class variable.

 

To be pedantic, 'this' is not an instance variable per say, but rather a pseudo-variable which in essence acts as a 'reference variable (or perhaps better phrased as an alias or object identifier) placeholder' which is 'the current instance of this class'. I think the term 'instance variable' is pretty much the object's properties.

 

Just to be really pedantic, when you're inside the scope of an object, the PHP engine will add a zval with type IS_OBJECT to EG(active_symbol_table) (a hash table containing all variables in the current scope) and give it the symbol name "this". It works like all other variables.

 

Internally in PHP, each "object" variable contains a reference to the object instance. So if $a is an object and you do $b = $a you'll add another entry in the symbol table that holds a reference to the same object instance. $this is stored in the symbol table in the same way as all other variables are.

 

When the manual says calls it a "pseudo-variable" it's more because it's something that's automatically created. Almost like magic :)

 

It has to work that way. Otherwise, if it wasn't holding a reference to the object like all other variables do, what would happen when you pass $this as an argument to a function or method? You're even allowed to do stupid things like unset($this); (though you can't reassign $this to something else).

 

That is my understanding of how the engine works anyway.

Link to comment
Share on other sites

Just to be really pedantic, when you're inside the scope of an object, the PHP engine will add a zval with type IS_OBJECT to EG(active_symbol_table) (a hash table containing all variables in the current scope) and give it the symbol name "this". It works like all other variables.

 

Internally in PHP, each "object" variable contains a reference to the object instance. So if $a is an object and you do $b = $a you'll add another entry in the symbol table that holds a reference to the same object instance. $this is stored in the symbol table in the same way as all other variables are.

 

Yep, that's ultra pedantic! :) I am aware of *zval containers and such (but wasn't aware of IS_OBJECT and EG though).

When a variable is copied, (a la $b = $a), it's simply PHP's way of optimizing storage, as it doesn't make sense for it to allocate more memory and store a copy of the value in question into it... (not at that point anyway) better off simply creating another reference that points to the same value until the value of either $a or $b changes...

 

That is my understanding of how the engine works anyway.

 

No disputes here.

 

 

[ot]

* For those who are curious about all this zval talk and what's it about, you can read this PDF article, which explains the nature of how variables work:

http://derickrethans.nl/files/phparch-php-variables-article.pdf

[/ot]

Link to comment
Share on other sites

[ot]

* For those who are curious about all this zval talk and what's it about, you can read this PDF article, which explains the nature of how variables work:

http://derickrethans.nl/files/phparch-php-variables-article.pdf

[/ot]

 

Lol... I took the more "direct" approach of trying to find my way around the source code :-\

 

Unfortunately, official resources about the inner workings of the engine are very sparse.

Link to comment
Share on other sites

Lol... I took the more "direct" approach of trying to find my way around the source code :-\

 

Unfortunately, official resources about the inner workings of the engine are very sparse.

 

I agree.. it would be nice if the say the PHP manual could create a whole new section that offers more info with regards to the inner workings of stuff like this for sure.. otherwise, yeah.. sparse is an understatement. I suppose resource would be to subscribe to PHP | Architect magazine?  :shrug: That's assuming it's still around.. too lazy to check lol

Link to comment
Share on other sites

So, if I define a class, and do not give it a constructor:

 

class ExampleClass
{
   private $name;
   public function getName() { return $this->name; }
}

 

Then what happens if I call it and pass it a parameter?

 

$blah = new ExampleClass("myName");

 

Will doing this still load it into the $name variable (by the "default constructor")?

 

I'm guessing not.

 

So, in general, when making a class, ALWAYS define a constructor?  Would you guys agree that that is generally true?

 

Another part that I find very weird is: why do you need the construct function at all?  Wouldn't it work better if you could define the class like this:

 

class MyClass ($one, $two, $three) {
   public function echoOne { echo $one; }
}

$blah = new MyClass(1,2,3);
$blah.echoOne;

//outputs "1";

 

Where the "constructor" is part of the definition of the class, instead of a function within it (like the way you define functions!) ??

 

There must be a reason why it is not done this way.

 

 

Just curious, too: I was looking back over the replies to this post.  I have seen this done lots of times as well and never quite undertood:

 

foreach($GLOBALS as $key => $val)

 

When you do this, are $key and $val predefined "pseudo variables" as well, that you can use to build the associative array?  Or could I use

 

foreach($GLOBALS as $fling => $poo)

 

and get the same result?

 

 

Thanks again  :shy:

Link to comment
Share on other sites

So, if I define a class, and do not give it a constructor:

 

class ExampleClass
{
   private $name;
   public function getName() { return $this->name; }
}

 

Then what happens if I call it and pass it a parameter?

 

$blah = new ExampleClass("myName");

 

Will doing this still load it into the $name variable (by the "default constructor")?

 

I'm guessing not.

 

No. If you don't define a constructor, it's the same thing as defining a constructor with no body and no parameters. In PHP, you can pass an infinite number of arguments to a function. The extra ones will just be discarded.

 

In your case, the return value of getName() would always be NULL. Variables in PHP are always initialized to NULL until they're given a value. This includes when you use an undefined variable (which you shouldn't).

 

So, in general, when making a class, ALWAYS define a constructor?  Would you guys agree that that is generally true?

 

Only if you have something you need to do in the constructor. It won't hurt doing it though. You just need to remember that if a child class defines a constructor, the parent class' constructor will not be called automatically. That becomes your responsibility when you define a constructor.

 

Another part that I find very weird is: why do you need the construct function at all?  Wouldn't it work better if you could define the class like this:

 

class MyClass ($one, $two, $three) {
   public function echoOne { echo $one; }
}

$blah = new MyClass(1,2,3);
$blah.echoOne;

//outputs "1";

 

Where the "constructor" is part of the definition of the class, instead of a function within it (like the way you define functions!) ??

 

There must be a reason why it is not done this way.

 

Mostly it's a matter of style. A reason might be that if you don't define properties, they won't be inherited by children classes and you cannot control the visibility. Also, the constructor is a real method that you can actually call. This is often done in a child class by doing like parent::__construct($something);. It also makes it easier to see what is part of the constructor and what isn't when it's defined in its own method.

 

Just curious, too: I was looking back over the replies to this post.  I have seen this done lots of times as well and never quite undertood:

 

foreach($GLOBALS as $key => $val)

 

When you do this, are $key and $val predefined "pseudo variables" as well, that you can use to build the associative array?  Or could I use

 

foreach($GLOBALS as $fling => $poo)

 

and get the same result?

 

They are not predefined variables. The foreach loops works by iterating over all the elements in an array (though foreach can be used on objects implementing the Traversable interface). For each element in the array it will bind the value of the key to $key and the value of the value to $val when you use $key => $val. You can choose whatever name you want.

Link to comment
Share on other sites

So, if I define a class, and do not give it a constructor:

 

class ExampleClass
{
   private $name;
   public function getName() { return $this->name; }
}

 

Then what happens if I call it and pass it a parameter?

 

$blah = new ExampleClass("myName");

 

Will doing this still load it into the $name variable (by the "default constructor")?

 

I'm guessing not.

 

You can always try it out.. experiment and see what happens. ;)

In your snippet, you are passing an argument, but since there is no explicit constructor declared, nothing will happen.. Constructors are used to initialize things.. so if you want to use the constructor way of doing things, you would need to add this constructor explicitly:

 

class ExampleClass {
   private $name;
   public function __construct($argName){
       $this->name = $argName;
   }
   public function getName() { return $this->name; }
}

$blah = new ExampleClass("myName");
echo $blah->getName();

 

 

Granted, you can initialize object properties dynamically, like so:

class ExampleClass {
   public function getName() { return $this->name; }
}

$blah = new ExampleClass();
$blah->name = 'Harry'; // this property is declared dynamically
echo $blah->getName(); // output: Harry

 

Notice that the class itself is missing the name property. This way, you can create and assign properties at run-time.. However, this practice is discouraged, because whenever a client coder (either yourself or someone else) sits down and instantiates that class, the name property will not exist by default.

 

Alternative to the constructor, you can use what is called setter and getter methods, also collectively known as accessor methods:

class ExampleClass {

    private $_name; // in some conventions, private properties / methods start with an underscore for easier visibility recognition by the programmer

    public function get_name() {
return $this->_name;
    }

    public function set_name($_name) {
$this->_name = $_name;
    }
}

$blah = new ExampleClass();
$blah->set_name('Harry'); // using setter accessor method to set a property
echo $blah->get_name(); // using a getter accessor method to fetch property

 

 

So, in general, when making a class, ALWAYS define a constructor?  Would you guys agree that that is generally true?

 

No.. remember, cexplicit constructors are typically treated as initializers.. they kick in when an object is created.. so if you want something done within the object on object creation, you use explicit constructors. Just understand that you don't absolutely require constructors.. its a case by case basis. You can always use accessor methods (setters and getters) as well (albeit with more code required from the client coder).

 

Ok.. so Dan responded already, so I'll stop here.. lol He beat me to it, and I don't feel like typing all this out for nothing, so I'll post anyway.

Link to comment
Share on other sites

In your snippet, you are passing an argument, but since there is no explicit constructor declared, nothing will happen..

 

Sorry, that's not entirely accurate.. the private property 'name' is set to null.. You can always check out aspects of you objects by using one of the following:

 

var_dump($blah);

echo '<pre>'.print_r($blah, true);  <---  this won't reveal as much info though

 

or if you really want to dig into an object's innards..one way could be to include the following method within your class body:

 

public function debug($mode = true) {
    if($mode) { // use PHP's built in reflection API
$rc = new ReflectionClass(self::$this);
echo '<pre>' . Reflection::export($rc, true);
    } else { // use debug_backtrace() instead
        echo '<pre>'.print_r(debug_backtrace(), true);
    }
}

 

So you'll get different reporting depending on whether an argument (which ultimately evaulates to true or false) is passed into the debug method:

So $blah->debug() will give you one reporting style, while $blah->debug(0); will report differently.

All this is is using the reflection API  in conjunction with debug_backtrack().

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.