note 93452 deleted from language.oop5.decon by danbrown
| From: | danbrown@php.net | Date: | Thu, 10 Sep 2009 15:08:43 +0000 |
| Subject: | note 93452 deleted from language.oop5.decon by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-160418@lists.php.net to get a copy of this message | ||
Note Submitter: edgar at goodforall dot eu
----
What I always found rather annoying about php5 is that I can't set the $this variable. (e.g.:
to encapsulate it into a proxy. Put stuff before and after certain methods etc). I have found a
workaround for that, which changes the syntax a bit of constructing an object:
<?php
new TestClass($p);
?>
It is a bit odd, but is still readable. $p now contains a proxy object, which encapsulates
TestClass. What I do is passing a reference to the class constructor. The constructor looks like
this:
<?php
class TestClass {
public function __construct(&$t){
/* Modify $this into method wrapper */
new MethodWrapper($this);
/* Assign $this to $t */
$t = $this;
}
public function test(){
print "Hello\n";
}
}
?>
I give my proxy a reference to $this. In the proxy the references of $this of TestClass and the
reference of the proxy are swapped:
<?php
class MethodWrapper {
protected $object;
/* Swap original and proxy object */
public function __construct(&$orig){
$swap = $orig;
$orig = $this;
$this->object = $swap;
}
/* Propagate calls to inner object, run methods before and after */
public function __call($method, $args){
$this->before(get_class($this->object),$method, $args);
$out = call_user_func_array(array($this->object, $method), $args);
/* push output as argument to after function */
array_unshift($args, $out);
$this->after(get_class($this->object),$method, $args);
return $out;
}
protected function after($class, $method, $args){
printf("After method: %s, %s \n", $class, $method);
}
protected function before($class, $method, $args){
printf("Before method: %s, %s \n", $class, $method);
}
}
?>
Which gives the following output:
<?php
new TestClass($p);
/* $p contains the TestClass encapsulated by the MethodWrapper class */
print_r($p);
$p->test();
/* output
MethodWrapper Object
(
[object:protected] => TestClass Object
(
)
)
Before method: TestClass, test
Hello
After method: TestClass
*/
?>