note 97181 added to language.oop5.inheritance

From: Date: Wed, 07 Apr 2010 09:36:31 +0000
Subject: note 97181 added to language.oop5.inheritance
Groups: php.notes 
Request: Send a blank email to php-notes+get-167745@lists.php.net to get a copy of this message
Here's fun, an attempt to make some degree of multiple inheritance work in PHP using mixins. It's not particularly pretty, doesn't support method visibility modifiers and, if put to any meaningful purpose, could well make your call stack balloon to Ruby-on-Rails-esque 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; } } ?> ---- Server IP: 69.147.83.197 Probable Submitter: 81.136.143.29 ---- Manual Page -- http://www.php.net/manual/en/language.oop5.inheritance.php Edit -- https://master.php.net/note/edit/97181 Del: integrated -- https://master.php.net/note/delete/97181/integrated Del: useless -- https://master.php.net/note/delete/97181/useless Del: bad code -- https://master.php.net/note/delete/97181/bad+code Del: spam -- https://master.php.net/note/delete/97181/spam Del: non-english -- https://master.php.net/note/delete/97181/non-english Del: in docs -- https://master.php.net/note/delete/97181/in+docs Del: other reasons-- https://master.php.net/note/delete/97181 Reject -- https://master.php.net/note/reject/97181 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#167745) next »