views:

173

answers:

3

What's the best way to do something like this in PHP?:

$a = new CustomClass();

$a->customFunction = function() {
    return 'Hello World';
}

echo $a->customFunction();

(The above code is not valid.)

+1  A: 

Unlike Javascript you can't assign functions to PHP classes after the fact (I assume you are coming from Javascript becuase you are using their anonymous functions).

Javascript has a Classless Prototypal system, where as PHP has a Classical Classing System. In PHP you have to define every class you are going to use, while in Javascript, you can create and change each object however you want.

In the words of Douglas Crockford: You can program in Javascript like it is a Classical System, but you can't program in a Classical System like it is Javascript. This means that a lot of the stuff you are able to do in Javascript, you can't do in PHP, without modifications.

Chacha102
A: 

I smell Adapter Pattern, or maybe even Decorator Pattern!

Peter Bailey
+4  A: 

Here is a simple and limited monkey-patch-like class for PHP. Methods added to the class instance must take the object reference ($this) as their first parameter, python-style. Also, constructs like parent and self won't work.

OTOH, it allows you to patch any callback type into the class.

class Monkey {

 private $_overload = "";
 private static $_static = "";


 public function addMethod($name, $callback) {
  $this->_overload[$name] = $callback;
 }

 public function __call($name, $arguments) {
  if(isset($this->_overload[$name])) {
   array_unshift($arguments, $this);
   return call_user_func_array($this->_overload[$name], $arguments);
   /* alternatively, if you prefer an argument array instead of an argument list (in the function)
   return call_user_func($this->_overload[$name], $this, $arguments);
   */
  } else {
   throw new Exception("No registered method called ".__CLASS__."::".$name);
  }
 }

 /* static method calling only works in PHP 5.3.0 and later */
 public static function addStaticMethod($name, $callback) {
  $this->_static[$name] = $callback;
 }

 public static function __callStatic($name, $arguments) {
  if(isset($this->_static[$name])) {
   return call_user_func($this->_static[$name], $arguments);
   /* alternatively, if you prefer an argument list instead of an argument array (in the function)
   return call_user_func_array($this->_static[$name], $arguments);
   */
  } else {
   throw new Exception("No registered method called ".__CLASS__."::".$name);
  }
 }

}

/* note, defined outside the class */
function patch($this, $arg1, $arg2) {
 echo "Arguments $arg1 and $arg2\n";
}

$m = new Monkey();
$m->addMethod("patch", "patch");
$m->patch("one", "two");

/* any callback type works. This will apply `get_class_methods` to the $m object. Quite useless, but fun. */
$m->addMethod("inspect", "get_class_methods");
echo implode("\n", $m->inspect())."\n";
gnud