note 97079 added to language.oop5.inheritance

From: Date: Wed, 31 Mar 2010 15:39:12 +0000
Subject: note 97079 added to language.oop5.inheritance
Groups: php.notes 
Request: Send a blank email to php-notes+get-167560@lists.php.net to get a copy of this message
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; } } ?> ---- Server IP: 78.110.173.36 Probable Submitter: 195.234.241.4 ---- Manual Page -- http://www.php.net/manual/en/language.oop5.inheritance.php Edit -- https://master.php.net/note/edit/97079 Del: integrated -- https://master.php.net/note/delete/97079/integrated Del: useless -- https://master.php.net/note/delete/97079/useless Del: bad code -- https://master.php.net/note/delete/97079/bad+code Del: spam -- https://master.php.net/note/delete/97079/spam Del: non-english -- https://master.php.net/note/delete/97079/non-english Del: in docs -- https://master.php.net/note/delete/97079/in+docs Del: other reasons-- https://master.php.net/note/delete/97079 Reject -- https://master.php.net/note/reject/97079 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#167560) next »