Extending objects with new methods at runtime



With the advent of PHP 5.3 adding new methods to an instance of a class at runtime becomes possible with PHP as well, using anonymous functions and a little bit of __call() magic. First, let's define a new class (boring old foo, bar, baz example for lack of fantasy):

class Foo { public function bar() { echo "This is Foo::bar()

"; } }



As you surely already know you can add public properties to an instance at any time:

$foo = new Foo(); $foo->baz = 'Hello World.'`;



We can use this to store an anonymous function:

$foo = new Foo(); $foo->baz = function () { echo "This is Foo::\$baz()

"; };



Unfortunately, we are not able to call this as a method:

$foo->baz();

This will blow up with a fatal error saying "Call to undefined method Foo::baz()". Of course we could do

$func = $foo->baz; $func();

but that is not what we wanted to achieve. Let's add some __call() magic to our Foo class:

class Foo { // method bar() omitted public function __call($method, $args) { if (isset($this->$method) === true) { $func = $this->$method; $func(); } } }

Now we can safely call $foo->baz() with the desired result. However, compared to Ruby you can not redefine existing methods. Therefore,

$foo->bar = function () { echo "This is Foo::\$bar()

"; }; $foo->bar();

will still call the method Foo::bar() defined earlier and ignore the redefinition due to the nature of how __call() works.



What can you do with it? If you use



Another use case could be a simplified version of the



If you have another good idea of what this can be used for please feel free to comment - just wanted to write my thoughts down.

While the title of this blog entry might sound rather scary to straight OO evangelists it might attract other developers - e.g. those that played around with runkit or had a look into the Ruby world where the language supports adding new methods to a class or just to an instance of a class at runtime (see singleton methods , and this blog article ; for those not familiar with Ruby: Fixnum is a class already defined by Ruby core.)With the advent of PHP 5.3 adding new methods to an instance of a class at runtime becomes possible with PHP as well, using anonymous functions and a little bit of __call() magic. First, let's define a new class (boring old foo, bar, baz example for lack of fantasy):As you surely already know you can add public properties to an instance at any time:We can use this to store an anonymous function:Unfortunately, we are not able to call this as a method:This will blow up with a fatal error saying "Call to undefined method Foo::baz()". Of course we could dobut that is not what we wanted to achieve. Let's add some __call() magic to our Foo class:Now we can safely call $foo->baz() with the desired result. However, compared to Ruby you can not redefine existing methods. Therefore,will still call the method Foo::bar() defined earlier and ignore the redefinition due to the nature of how __call() works.What can you do with it? If you use duck typing this might be useful as it reduces the amount of code required for the Adapter design pattern as you just extend the instance you want to use instead of creating a separate adapter class. The result is the same, both a full fledged adapter class and the closure can only access the public properties and methods of the instance to adapt. Problem is, the class to adapt most likely does not have the required __call() implementation.Another use case could be a simplified version of the extension methods mechanism where you want to add a method locally without the need to have it available globally in the application.If you have another good idea of what this can be used for please feel free to comment - just wanted to write my thoughts down.

