Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to dynamically add code to/extend a class?

Tags:

php

I want to write a sort of "plugin/module" system for my code, and it would make it much easier if I could "add" stuff into a class after it's been defined.

For example, something like this:

class foo {
  public function a() {
     return 'b';
  }
}

There's the class. Now I want to add another function/variable/const to it, after it's defined.

I realize that this is probably not possible, but I need confirmation.

like image 867
Savetheinternet Avatar asked Dec 29 '22 02:12

Savetheinternet


2 Answers

No, you cannot add methods to an already defined class at runtime.

But you can create similar functionality using __call/__callStatic magic methods.

Class Extendable  {
    private $handlers = array();
    public function registerHandler($handler) {
        $this->handlers[] = $handler;
    }

    public function __call($method, $arguments) {
        foreach ($this->handlers as $handler) {
            if (method_exists($handler, $method)) {
                return call_user_func_array(
                    array($handler, $method),
                    $arguments
                );
            }
        }
    }
}

Class myclass extends Extendable {
    public function foo() {
        echo 'foo';
    }
}

CLass myclass2 {
    public function bar() {
        echo 'bar';
    }
}

$myclass = new myclass();
$myclass->registerHandler(new myclass2());

$myclass->foo(); // prints 'foo'
echo "\n";

$myclass->bar(); // prints 'bar'
echo "\n";

This solution is quite limited but maybe it will work for you

like image 59
German Rumm Avatar answered Jan 08 '23 01:01

German Rumm


To add/change how classes behave at runtime, you should use Decorators and/or Strategies. This is the prefered OO approach over resorting to any magic approaches or monkey patching.

A Decorator wraps an instance of a class and provides the same API as that instance. Any calls are delegated to the wrapped instance and results are modified where needed.

class Decorator 
{
    // …

    public function __construct($decoratedInstance)
    {
        $this->_decoratedInstace = $decoratedInstance;    
    }
    public function someMethod()
    {
        // call original method
        $result = $this->_decoratedInstance->someMethod();
        // decorate and return
        return $result * 10;
    }
    // …
}

For Strategy, see my more complete example at Can I include code into a PHP class?

More details and example code can be found at

  • http://sourcemaking.com/design_patterns/decorator
  • http://sourcemaking.com/design_patterns/strategy
like image 42
Gordon Avatar answered Jan 08 '23 02:01

Gordon