Here is an example of one way to define, then use the variable ( $this ) in Closure functions. The code below explores all uses, and shows restrictions.
The most useful tool in this snippet is the requesting_class() function that will tell you which class is responsible for executing the current Closure().
Overview:
-----------------------
Successfully find calling object reference.
Successfully call $this(__invoke);
Successfully reference $$this->name;
Successfully call call_user_func(array($this, 'method'))
Failure: reference anything through $this->
Failure: $this->name = '';
Failure: $this->delfect();
<?php
function requesting_class()
{
foreach(debug_backtrace(true) as $stack){
if(isset($stack['object'])){
return $stack['object'];
}
}
}
class Person
{
public $name = '';
public $head = true;
public $feet = true;
public $deflected = false;
function __invoke($p){ return $this->$p; }
function __toString(){ return 'this'; } // test for reference
function __construct($name){ $this->name = $name; }
function deflect(){ $this->deflected = true; }
public function shoot()
{ // If customAttack is defined, use that as the shoot resut. Otherwise shoot feet
if(is_callable($this->customAttack)){
return call_user_func($this->customAttack);
}
$this->feet = false;
}
}
$p = new Person('Bob');
$p->customAttack =
function(){
echo $this; // Notice: Undefined variable: this
#$this = new Class() // FATAL ERROR
// Trick to assign the variable '$this'
extract(array('this' => requesting_class())); // Determine what class is responsible for making the call to Closure
var_dump( $this ); // Passive reference works
var_dump( $$this ); // Added to class: function __toString(){ return 'this'; }
$name = $this('name'); // Success
echo $name; // Outputs: Bob
echo '<br />';
echo $$this->name;
call_user_func_array(array($this, 'deflect'), array()); // SUCCESSFULLY CALLED
#$this->head = 0; //** FATAL ERROR: Using $this when not in object context
$$this->head = 0; // Successfully sets value
};
print_r($p);
$p->shoot();
print_r($p);
die();
?>