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, <davidgeb...@gmail.com> 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 <sarke...@gmail.com> 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, <davidgeb...@gmail.com> > 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 > >> > > >