note 97079 deleted from language.oop5.inheritance by danbrown

From: Date: Wed, 31 Mar 2010 16:25:27 +0000
Subject: note 97079 deleted from language.oop5.inheritance by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-167580@lists.php.net to get a copy of this message
Note Submitter: php at sleep is the enemy dot co dot uk ---- Here's fun, a little experiment to get some multiple inheritance working in PHP using mixins, a mixin class. It's not particularly pretty, doesn't support visibility modifiers and, if put to any sensible use, could make your call stack balloon to Ruby-on-Railsesque proportions but it does work. <?php abstract class Mix { protected $_mixMap = array(); public function __construct(){ $this->_mixMap = $this->collectMixins($this); } public function __call($method, $args){ // doesn't pass scope //return call_user_func_array(array($className, $method), $args); // Error: Given object is not an instance of the class this method was declared in //$method = new ReflectionMethod($className, $method); //return $method->invokeArgs($this, $args); $payload = $this->buildMixinPayload($this->_mixMap, $method, $args); if(!$payload) throw new Exception('Method ' . $method . ' not found'); list($mixinMethod, list($method, $args)) = $payload; return $this->$mixinMethod($method, $args); } protected function collectMixins($class){ static $found = array(); static $branch = array(); if(empty($branch)) $branch[] = get_class($this); $mixins = array(); foreach(array_reverse(get_class_methods($class)) as $method){ if(preg_match('/^mixin(\w+)$/', $method, $matches)){ $className = $matches[1]; if(in_array($className, $branch)) throw new Exception('Circular reference detected ' . implode(' > ', $branch) . ' > ' . $className); if(!in_array($className, $found)){ if(!class_exists($className)) throw new Exception('Class ' . $className . ' not found'); // populate props from mixin class foreach(get_class_vars($className) as $key => $value){ if(!property_exists($this, $key)) $this->$key = $value; } $found[] = $branch[] = $className; $mixins[$className] = $this->collectMixins($className); } $branch = array(get_class($this)); } } return $mixins; } protected function buildMixinPayload($mixins, $method, $args){ foreach($mixins as $className => $parents){ $mixinMethod = 'mixin' . $className; if(method_exists($className, $method)) return array($mixinMethod, array($method, $args)); if(!empty($parents) && $return = $this->buildMixinPayload($parents, $method, $args)){ return array($mixinMethod, $return); } } return false; } } ?>

« previous php.notes (#167580) next »