'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