7

我对正在为我的自定义框架开发的事件系统有一个想法。

想象一个像这样的伪函数。

class Test
{
    public function hi()
    {
        Event::add(__FUNCTION__ . 'is about to run.');
        return "hi";
    }
}

想象一下,您需要为更多功能做同样的事情。(也许您想记录在运行时运行的函数并希望将它们记录在单独的文件中。)

除了手动将事件添加到函数中,我们可以做这样的事情吗?

class Test
{
    public function hi()
    {
        return "hi";
    }
}

// events.php (It's a pseudo code so may not work.)
// Imagine extend's purpose is to inject codes into target function

Event::bind('on', $className, $methodName, function() use ($className, $methodName) 
{
    return $className->$methodName->extend('before', Event::add(__FUNCTION__ . 'is about to run.'));
});

这个想法是注入hi()内部的函数,并从外部Test class注入我们在函数中传递的任何内容extend'before'意味着注入必须在目标函数的第一行。

最后,事件和事件绑定完全从函数中抽象出来。我希望能够在不改变功能的情况下绑定自定义的东西。

我有一种感觉,我们可以通过修改eval()或玩弄call_user_func(). 不过,我不确定。使用eval()听起来已经很糟糕了。

我的问题是;

  1. 有可能与PHP有关吗?
  2. 它是否在 OOP/OOP 原则中有名称,以便我可以进一步阅读?
  3. 它有任何意义还是一个坏主意?
4

1 回答 1

2

是的你可以。您可以通过GO使用AOP !处理注释的AOP 框架

例如,您想记录每个公共方法调用。而不是像这样添加到每个功能行。

namespace Acme;

class Controller
{
    public function updateData($arg1, $arg2)
    {
        $this->logger->info("Executing method " . __METHOD__, func_get_args()); 
        // ...
    }    
}

您可以对 Acme 命名空间的所有类的所有公共方法使用一个方面,如下所示:

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;

    class LoggingAspect implements Aspect
    {
        /** @var null|LoggerInterface */
        protected $logger = null;

        /** ... */
        public function __construct($logger) 
        {
            $this->logger = $logger;
        }

        /**
         * Method that should be called before real method
         *
         * @param MethodInvocation $invocation Invocation
         * @Before("execution(public Acme\*->*())")
         */
        public function beforeMethodExecution(MethodInvocation $invocation)
        {
            $obj    = $invocation->getThis();
            $class  = is_object($obj) ? get_class($obj) : $obj;
            $type   = $invocation->getMethod()->isStatic() ? '::' : '->';
            $name   = $invocation->getMethod()->getName();
            $method = $class . $type . $name;

            $this->logger->info("Executing method " . $method, $invocation->getArguments());
        }
    }    

它看起来更复杂,但更灵活。

于 2013-05-20T00:49:26.947 回答