'Twas brillig, and Mike at 03/01/11 23:37 did gyre and gimble: > I'm trying to design a powerful plugin system that doesn't require any > (or extremely little) modification to my existing large code base. Hook > based systems unfortunately don't seem to meet this requirement. > > Is something like this possible in PHP? > > //Magic function I made up, similar to __call(), > //only it replaces "new $class" with its own return value. > function __instantiate( $class, $args ) { > $plugin_class = $class.'Plugin'; > > if ( file_exists( 'plugins/'.$plugin_class.'.php' ) { > $obj = new $plugin_class($args); > return $obj; > } else { > return new $class($args); > } > } I'd implement the above as a static "factory" method of your primary class: e.g. > class MainClass { public static function factory($args = null) { $plugin_class = __CLASS__ . 'Plugin'; // Assume autoloading.... if (class_exists($plugin_class)) return new $plugin_class($args); return new self($args); } protected function __construct($args) { } > function doSomething( $args ) { > echo "MainClass doSomething() called...\n"; > } > } > > class MainClassPlugin extends MainClass { > function doSomething( $args ) { > echo "MainClassPlugin doSomething() called...\n"; > > //Modify arguments if necessary > echo "MainClassPlugin modifying arguments...\n"; > > $retval = parent::doSomething( $args ); > > //Modify function output, or anything else required > echo "MainClassPlugin post filter...\n"; > > return $retval; > } > } > > $main_class = new MainClass(); And replace this line with: $main_class = MainClass::factory(); > $main_class->doSomething( 'foo' ); Which, when run, does indeed produce your desired results. > Results: > MainClassPlugin doSomething() called... > MainClassPlugin modifying arguments... > MainClass doSomething() called... > MainClassPlugin post filter... > > I realize PHP doesn't have this magical "__instantiate" function, but > does it have any similar mechanism that would work to automatically > load alternate classes, or have a class dynamically overload > itself during runtime? Well difference techniques require different approaches, but certainly a factory approach is likely the correct design solution here to get the desired results. Full code for convenience: <?php class MainClass { public static function factory($args = null) { $plugin_class = __CLASS__ . 'Plugin'; // Assume autoloading.... if (class_exists($plugin_class)) return new $plugin_class($args); return new self($args); } protected function __construct($args) { } function doSomething( $args ) { echo "MainClass doSomething() called...\n"; } } class MainClassPlugin extends MainClass { function doSomething( $args ) { echo "MainClassPlugin doSomething() called...\n"; //Modify arguments if necessary echo "MainClassPlugin modifying arguments...\n"; $retval = parent::doSomething( $args ); //Modify function output, or anything else required echo "MainClassPlugin post filter...\n"; return $retval; } } $main_class = MainClass::factory('wibble'); $main_class->doSomething( 'foo' ); -- Colin Guthrie gmane(at)colin.guthr.ie http://colin.guthr.ie/ Day Job: Tribalogic Limited [http://www.tribalogic.net/] Open Source: Mageia Contributor [http://www.mageia.org/] PulseAudio Hacker [http://www.pulseaudio.org/] Trac Hacker [http://trac.edgewall.org/] -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php