I just checked in a fancy change to ZMObject that allows to dynamically add methods to any class (assuming the class extends from ZMObject) at runtime.
So, what’s the deal? you ask? Well, I always have been slightly uncomfortable about the fact that if multiple plugins wanted to extend/modify an existing core class, say, for example, ZMProduct, there could be only a single winner.
The alternative is to add new services and use them in templates. Of course, that is ok and all, but wouldn’t it be much cooler to just use the affected class directly without something like the following?
$value = MyService ::instance()->getFoo($product);
So, compare that with:
$value = $product->getFoo();
And here is how this can be done:
class MyService {
/**
* @param mixed target The instance the method was invoked on (instance of ZMProduct).
* @param var ... some Some single parameter.
*/
public function getFoo($target, $some) {
return "foo: ".$some.": ".$target->getName();
}
}
ZMObject::attachMethod(‘getFoo’, ‘ZMProduct’, array(new MyService (), ‘getFoo’));
$product = ZMProducts::instance()->getProductForId(3);
echo $product->getFoo(‘xx’);
So, what does it do?
- First there is a new class that implements the calculation of the new property.
- Next we attach an instance of MyService as handler of
getFoo calls on ZMProduct objects
- Load a product from the database
- call
getFoo('xx') on $product
The same works if the handler is a simple function:
ZMObject::attachMethod('getFoo', 'ZMProduct', create_function('$target, $some', 'return "foo: ".$some.': '.$target->getName();'));
Another of those things that are not strictly necessary, but nice to look at