Hi again David,
I've been thinking about this some more, it could be quite useful.
I'd like to propose a bit more of a Attributes-y syntax:
```
<?php
#[Decorator(Decorator::TARGET_METHOD)]
// or
#[Attribute(Attribute::DECORATOR_METHOD)]
class Timer
{
private $start;
public function __construct(
private string $name = 'Tim',
)
{
$this->start = microtime(true);
// these could be made available
$foo = $this->getObject();
$args = $this->getArguments(); // [$a, $b]
$ref = $this->getReflection();
}
public function __destruct()
{
$end = microtime(true);
$total = $end - $start;
echo "Executed {$this->name} in $total second(s)\n";
}
}
class Foo
{
#[Timer]
public function bar($a, $b) { ... }
#[Timer('Bob')]
public function baz($a, $b) { ... }
}
```
Thanks,
Peter
On Sat., Mar. 13, 2021, 15:04 David Gebler, <[email protected]> wrote:
> Decorators are a way of bringing aspect oriented programming into PHP core,
> yes, among other uses. Go AOP is a fairly bulky framework which could be
> easily replaced by a Decorator attribute for the purposes of cross-cutting
> changes to function behaviour.
>
> Regards,
> David
>
> On Sat, Mar 13, 2021 at 10:51 PM Peter Stalman <[email protected]> wrote:
>
> > Hi David,
> >
> > This sounds a lot like Asect Oriented Programming. Have you looked into
> > that?
> >
> > PHP framework:
> > https://github.com/goaop/framework
> >
> > PECL extension:
> > https://aop-php.github.io/
> >
> > Thanks,
> > Peter
> >
> >
> >
> > On Sat., Mar. 13, 2021, 08:51 David Gebler, <[email protected]>
> wrote:
> >
> >> With the introduction of attributes in PHP 8, this new behaviour is
> still
> >> quite sparsely documented. Some of the articles I've seen out there,
> >> though, liken PHP's attributes to similar constructs in other languages
> >> including decorators in Python.
> >>
> >> Attributes are not the same thing as (Python's concept of) decorators
> and
> >> they shouldn't be confused; a decorator is a function which wraps
> another
> >> function and is automatically called in place of the wrapped function.
> >>
> >> This isn't currently possible in PHP. Using frameworks like Symfony, we
> >> can
> >> start to build things like this:
> >>
> >> class UserProfileController {
> >> #[LoginRequired]
> >> public function editProfile(...) { }
> >> }
> >>
> >> but the logic of enforcing our "require the user to be logged in"
> >> decorator
> >> relies on the surrounding framework controlling the flow of execution,
> >> reading the attribute and deciding whether to call the decorated method
> >> editProfile() at all.
> >>
> >> What we *can't* do is something like this:
> >>
> >> class Foo {
> >> private function timer(callable $wrapped)
> >> {
> >> $start = microtime(true);
> >> $wrapped();
> >> $end = microtime(true);
> >> $total = $end - $start;
> >> echo "Executed function in $total second(s)\n";
> >> }
> >>
> >> #[timer]
> >> public function bar($a, $b) { ... }
> >>
> >> #[timer]
> >> public function baz($a, $b) { ... }
> >> }
> >>
> >> What I'm wondering is whether there's a desire / interest for a built-in
> >> attribute to provide this kind of behaviour modification.
> >>
> >> I'm thinking something like
> >>
> >> class Foo {
> >> private function timer(callable $wrapped) { ... }
> >>
> >> #[Decorator([self::class, 'timer'])]
> >> public function bar() {
> >> echo "Bar";
> >> }
> >> }
> >>
> >> Where this would result in any call to $foo->bar() being equivalent to
> as
> >> if the above were defined as:
> >>
> >> class Foo {
> >> private function timer(callable $wrapped) { ... }
> >>
> >> public function __bar() {
> >> echo "Bar";
> >> }
> >>
> >> public function bar() {
> >> return $this->timer([$this, '__bar']);
> >> }
> >> }
> >>
> >> I'm not saying I have the skills to implement this attribute (though I'd
> >> happily try), I'm not even in a position to propose a draft RFC at this
> >> stage, just throwing the idea out there to get a feel for what people
> >> think
> >> of the concept?
> >>
> >> Regards,
> >> Dave
> >>
> >
>