I'll start with the word "Thank you" grrbrr404. He gave me some ideas and started me in the right direction.
The solution I finally stopped was as follows:
function inherit_this() { $bt = debug_backtrace(); call_user_func(array($this, get_parent_class($bt[1]['class']) . '::do_something')); }
This is not very (I especially hate to call debug_backtrace()
for this), but it maintains the object context set to $ this and handles the case when a method is called from a method somewhere in the middle of the hierarchy of objects.
For those who found my example confusing and / or wanted to know "Why do you want to do this?" We apologize and give the following additional example, which we hope will be more visible and closer to the original problem. This is much longer, but I hope it shows why I care about properly supporting this set, and also shows why I cannot hardcode any particular class name or use the this this-> method () method. Avoiding endless loops is always a priority for me. :-)
class class1_required_type { } class class2_required_type { } class class3_required_type { } class class4_required_type { } class class1 { protected $data = array(); protected function checkType($name, $value, $requiredType) { print "In class1::checkType()\n"; if (get_class($value) === $requiredType) { $backtrace = debug_backtrace(); call_user_func(array($this, get_parent_class($backtrace[1]['class']) . "::mySet"), $name, $value); } else { throw new Exception(get_class($this) . "::mySet('" . $name . "') requires an object of type '" . $requiredType . "', but got '" . get_class($value) . "'"); } } function mySet($name, $value) { print "In class1::mySet()\n"; if ($name === 'class1_field') { $this->checkType($name, $value, 'class1_required_type'); } else { $this->data[$name] = $value; } } function dump() { foreach ($this->data as $key => $value) { print "$key: " . get_class($value) . "\n"; } } } class class2 extends class1 { function mySet($name, $value) { print "In class2::mySet()\n"; if ($name === 'class2_field') { $this->checkType($name, $value, 'class2_required_type'); } else { parent::mySet($name, $value); } } } class class3 extends class2 { function mySet($name, $value) { print "In class3::mySet()\n"; if ($name === 'class3_field') { $this->checkType($name, $value, 'class3_required_type'); } else { parent::mySet($name, $value); } } } class class4 extends class3 { function mySet($name, $value) { print "In class4::mySet()\n"; if ($name === 'class4_field') { $this->checkType($name, $value, 'class4_required_type'); } else { parent::mySet($name, $value); } } } $obj = new class4; $obj->mySet('class3_field', new class3_required_type); $obj->dump();
I try to avoid duplication of the "checkType ()" function, but at the same time keep the correct behavior, even if the hierarchy becomes arbitrarily large.
More elegant solutions are, of course, most welcome.