Hello all, I've had an idea that's been burning in my head for a while. Rather than write an RFC or do any significant work on it, I thought I would bounce this off of you all first.
Basically, I see a problem with implementing decorators in PHP. To explain the problem, let's say that I have a class that I want to decorate that implements IteratorAggregate and Countable. Right now, to decorate that properly I would need to make the following class: class MyDecorator implements IteratorAggregate, Countable { protected $object = null; public function __construct($object) { $this->object = $object; } public function __call($name, $args) { return call_user_func_array(array($this->object, $name), $args); } public function getIterator() { return $this->object->getIterator(); } public function count() { return $this->object->count(); } public function addedFunctionality() { //blah } } And that's for two interfaces implementing one method each. Imagine implementing a dozen methods. That's a lot of duplication. Now, with traits we could add a trait for each interface which proxies back to `$this->object`. But that's still a lot of duplication and hard-coding. So, I've been trying to think of a few methods to add syntactic sugar to PHP to make this a lot easier. So here's my thoughts Option 1 Add a magic interface `\PHP\Decorator` which would declare a `getDecoratedObject()` method. It would after construction call that method to figure out what interfaces the decorated object uses. Then, it would magically implement them (as above) on the class if they weren't already implemented (overridden). That way the decorated object could be resolved at runtime. I'm not sold on this concept as it feels a bit too "magic" to me. class MyDecorator implements \PHP\Decorator { protected $object; public function __construct($object) { $this->object = $object; } public function getDecoratedObject() { return $this->object; } public function addedFunctionality() { // blah } } Option 2 Implement a magic interface `\PHP\Decorator` which would then allow all declared interfaces to be satisfied by `__call`. This should require the least change to the core, since the only real change that's needed is in the core where it checks that the declared interface is satisfied. class MyDecorator implements IteratorAggregate, Countable { protected $object = null; public function __construct($object) { $this->object = $object; } public function __call($name, $args) { return call_user_func_array(array($this->object, $name), $args); } public function addedFunctionality() { // blah } } Option 3 Add syntax to the member declaration that lets you declare which methods should be proxied to a member object. So something like this: class MyDecorator implements IteratorAggregate, Countable { protected $object decorates { public function getIterator(); public function count(); } public function __construct($object) { $this->object = $object; } public function addedFunctionality() { // blah } } Then, at compile time the core could do a replace on the class to add the proxy methods. This has a major advantage in that you could use multiple classes to selectively satisfy an interface. So you could actually use it to compose an object at compile time that proxies to multiple objects. Personally, I like the explicitness of Option 3, but I could get behind Option 2 as well. Option 1 feels a bit too magic for my tastes. Another thought, should a decorator be able to pass the type hint that the decorated object can pass? For example, should `new MyDecorator(new PDO)` be able to pass `__construct(PDO $pdo);`? If so, how would that be handled? Would the `Decorates` line automagically insert the decorator in the class hiearchy for type checking only? Or is that a bad idea in general (I have a feeling it is)... What are your thoughts? Anthony -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php