goaop / framework

:gem: Go! AOP PHP - modern aspect-oriented framework for the new level of software development
go.aopphp.com
MIT License
1.66k stars 163 forks source link

Support method invocation on Generators #443

Closed bartvanhoutte closed 4 years ago

bartvanhoutte commented 4 years ago

I'm trying to implement Go! AOP in a RecoilPHP coroutine but I'm running into one problem.

Having the following code:

/**
 * @FooAnnotation
 */
public function bar(): Generator

and the following aspect:

/**
 * @Around("FooAnnotation")
 */
public function fooAspect(MethodInvocation $invocation) {
  yield $invocation->proceed();

yield $invocation->proceed fails with this error: ReflectionMethod::getClosure() expects parameter 1 to be object, null given in DynamicClosureMethodInvocation.php on line 47

This is solved by changing AbstractMethodInvocation.php on line 89:

if ($this->reflectionMethod->isGenerator()) {
  yield $this->proceed();
} else {
  return $this->proceed();
}
lisachenko commented 4 years ago

Hi, @bartvanhoutte

Thank you for reporting this issue.

I'm not sure about if it should be allowed to use yield within advice body. Current logic requires to return values from advice body, even if it is Generator, so you can not use yield within advice body itself.

Maybe you could describe what kind of logic do you want to implement in aspect?

bartvanhoutte commented 4 years ago

I wanted to make aspects asynchronous using RecoilPHP, but with PHP lacking async support this is rather cumbersome. I've decided to go a different route.