Can we insert a few more lines into the function, expanding it with PHP?

I have an idea for an event system that I am developing for my own platform.

Imagine a pseudo-function like this.

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

Imagine you need to do the same for some other functions. (Perhaps you want to log what functions were executed at run time, and want to write them to a separate file.)

Instead, and adding events to functions manually, can we do something like this?

 class Test { public function hi() { return "hi"; } } // events.php (It a pseudo code so may not work.) // Imagine extend 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.')); }); 

The idea is to introduce the hi() function, which is inside the Test class and inject everything we pass into extend with the function outside. 'before' means that the injection should be on the first line of the target function.

Finally, events and event bindings are completely abstracted from functions. I want to be able to bind custom things without changing functions.

I have a feeling that we can do this by hacking eval() or by playing with call_user_func() . Although I'm not sure. Using eval() sounds pretty bad already.

My question is:

  • Is it possible to do this with PHP?
  • Does he have a name in OOP / OOP principles so that I can read further?
  • Does it make sense or is it a bad idea?
+7
source share
1 answer

Yes, you can. You can use AOP using GO! AOP that works on annotations.

For example, you want to register every call to a public method. Instead of adding to each function line like this.

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

You can use one Aspect for all public methods of all Acme namespace classes, for example:

 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()); } } 

It looks more complex, but it is more flexible.

+2
source

All Articles