# Thoughts On Implementing Decorator Sugar to core

- Thread: https://externals.io/message/56513
- Original archive: https://news-web.php.net/php.internals/56513
- Started by Anthony Ferrara on 2011-11-23T15:24:25+00:00
- Messages: 4
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #56513 — Anthony Ferrara — 2011-11-23T15:24:25+00:00

URL: https://externals.io/message/56513#56513

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

---

## #56583 — Larry Garfield — 2011-11-24T20:53:55+00:00

URL: https://externals.io/message/56513#56583 · In reply to: #56513

*snip*

> 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.

I've run into this issue before myself.  It's especially a problem when 
you're specifying a parameter type, because that means you can't just 
use __call().

It's also a problem then when you are stacking decorators.

class A implements Foo {
   // a dozen methods from Foo
}

class B implements Foo {
   // A dozen methods from Foo, all of which just call $this->a->X();
   public function newStuff() {}
}

class C implements Foo {
   // A dozen methods from Foo, all of which just call $this->a->X();
}

$c = new C(new B(new A)));

$c->newStuff(); // Fail, unless you use __call(), in which case you 
can't type hint on B.


> 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
>      }
> }

I don't see this as too much magic; it's really no more magical than the 
Countable or Iteratable interfaces.  "Funky cool language functionality 
triggered by an interface".  The advantage here is that it would give 
you lots of flexibility as to what the object to decorate is; it could 
be one passed in, or one instantiated internally, or one extracted from 
an object that's passed in, etc.  It would require documenting precisely 
when getDecoratedObject() is called.  I'd recommend that it get called 
right after the constructor finishes.

Alternatively, could it be an internal-only setter?  Call 
->setDecoratedObject() somewhere within the class and that's the object 
that gets magically passed through to.  Not sure if that works with an 
interface, though, since we wouldn't want that to be public.

> 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
>      }
> }

I don't like this approach.  One, it basically says "if I put this 
interface on my class, disable type checking".  That defeats the 
purpose.  It also has the problem that you can then only decorate one 
object (as noted in option 3).  Also, stacking __call() and 
 `call_user_func_array()` is one of the slowest things you can do in the 
language, in my testing, as well as making life much more difficult for 
people trying to debug code.

> 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.

I like the flexibility here.  It also seems consistent with the trait 
syntax, I think.  My only question is if we'd want to allow a short-hand 
to say that $object satisfies all methods on a given interface.  If your 
interface has a dozen methods, that's still a dozen lines of code you 
would need (and need to update if the interface ever changes).  So maybe:

class MyDecorator implements IteratorAggregate, Countable {
   protected $object decorates IteratorAggregate, {
     public function `count()`;
   }
}

(Or something.)

> 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.

I could live with 1 or 3, but not 2.  3 seems the most robust, but needs 
some thinking through first.

> 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)...

I'm not sure what you're suggesting here.  Are you asking if a class 
should magically inherit the interfaces of an object it decorates? 
That's... I don't know if that would work, honestly. :-)  It also goes 
to the inevitable tug-of-war behind being a strict language vs. a 
dynamic language.

> What are your thoughts?
>
> Anthony

Cautiously positive on the concept.

--Larry Garfield

---

## #56656 — Matthew Weier O'Phinney — 2011-11-28T17:57:40+00:00

URL: https://externals.io/message/56513#56656 · In reply to: #56513

> 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.  

Oof, yes. :)

<snip>

> 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.  

This seems reasonable, but there are some pretty big drawbacks as well:

 * Type-hinting -- typically, a decorator should be able to be used
   wherever the object it decorates is used. As such, if you simply
   implement PHP\Decorator, type-hinting breaks.

 * It looks like it would require a particular constructor pattern,
   which could be problematic. (You don't actually specify if the
   constructor is the only means for injection, so I can give you the
   benefit of the doubt here.)

The primary problem is the first listed, though, and it's pretty big --
I'd expect it would have large ramifications on Reflection, as well as
on various editors and IDEs to provide hinting.

<snip>

> 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.

The problem with this is similar to that of Option 1 -- by using
__call(), you lose Reflection and hinting capabilities.

<snip>

> 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.

I _really_ like this option, to be honest. My only nitpick is that, like
Option 1, we need to flesh out how the object to be decorated is
injected into the decorator. Otherwise, this answers the problems I
raised in Option 1 and Option 2.

> 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);`?  

in good OOP, you should be typehinting on
interfaces, not concrete implementations; following that logic, it's no
necessary. However, this breaks when decorating internal classes, where
there typically aren't interfaces. So my vote is that the hint be passed
on to the decorator. I have no idea how that would be handled, though.

> 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?


-- 
Matthew Weier O'Phinney
Project Lead            | matthew@zend.com
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

---

## #56665 — Anthony Ferrara — 2011-11-28T22:12:06+00:00

URL: https://externals.io/message/56513#56665 · In reply to: #56656

Comments Inline

On Mon, Nov 28, 2011 at 12:57 PM, Matthew Weier O'Phinney
<weierophinney@php.net> wrote:

> This seems reasonable, but there are some pretty big drawbacks as well:
>
>  * Type-hinting -- typically, a decorator should be able to be used
>   wherever the object it decorates is used. As such, if you simply
>   implement PHP\Decorator, type-hinting breaks.

Well, not quite.  Basically, what I was thinking of is this:

1. On instantiation, copy the class to a new anonymous class.
2. Set the parent of this anonymous class to the decorated object
3. Instantiate that new anonymous class.

So basically it could satisfy all type-hints for the decorated object,
since it's literally in the tree.

I admit this is quite dirty, but the changes would be pretty localized
to just the instantiation parts, since the other bits (type hinting)
are resolved normally at runtime.

>  * It looks like it would require a particular constructor pattern,
>   which could be problematic. (You don't actually specify if the
>   constructor is the only means for injection, so I can give you the
>   benefit of the doubt here.)

Well, the only thought I have would be to use the constructor.  But if
there are other options, great...

> The primary problem is the first listed, though, and it's pretty big --
> I'd expect it would have large ramifications on Reflection, as well as
> on various editors and IDEs to provide hinting.

Yeah, that's a kick...  And a pretty big one at that...

> The problem with this is similar to that of Option 1 -- by using
> __call(), you lose Reflection and hinting capabilities.

Agree...

> I _really_ like this option, to be honest. My only nitpick is that, like
> Option 1, we need to flesh out how the object to be decorated is
> injected into the decorator. Otherwise, this answers the problems I
> raised in Option 1 and Option 2.

Honestly, I could care less about that.  Since it's a normal field, it
could be done *after* instantiation (through a getter/setter), or even
modified on the fly.  The key would be to do one of two things.

1.  Check on each access of the decorated members that it's an object
and implements the correct method(s) - with the possible performance
issues there.  If not, you'd get a Fatal Error for call to member
function on non-object if it didn't exist, and a new error if it did,
but didn't implement the method (call to undefined method on object,
not resolvable by __call)...
2. Check on "setting" of the property that it implements the proper
methods.  This would only happen once (when it's set) to boost
performance.  Then, the access check would just see if it was null
(not set yet).  So that means it should be pretty performant.

But this involves the creation of a "magic property" type which would
execute code (granted, c level code) on setting...  Which may bring
its own headaches...

> in good OOP, you should be typehinting on
> interfaces, not concrete implementations; following that logic, it's no
> necessary. However, this breaks when decorating internal classes, where
> there typically aren't interfaces. So my vote is that the hint be passed
> on to the decorator. I have no idea how that would be handled, though.

Well, perhaps we could edit the `instanceof` handler to check to see
if it's a decorator object, and magically handle that as well.
Although that could cause some very interesting behavior as well, so
perhaps not the best.

In other thoughts, perhaps just implement interfaces for the all of
the core classes...  That way at least the problem is "worked around"
in practice...



Thanks for the feedback!!!
