Trigger an event when a function is called in a class

Is it possible in PHP to trigger an event whenever a function in a class is called without adding it to all the functions of the class?

Example:

<?php class A { function xxx() { //this function will be called everytime I call another function in this class } public static function b() { return 'Hello Stackoverflow!'; } public static function c() { //I also want this function to trigger the event! } } echo A::b(); ?> 
+4
source share
4 answers

AFAIK for this there are no constructs for the native language. If you need this for debugging purposes, I would advise you to take a deeper look at the xdebug extension, especially function tracking (awesome! :)

Another idea is to implement __call() in your class and wrap all public methods. But this requires changing the code and other side effects:

(simplified example)

 class Test { protected $listeners; public function __construct() { $this->listeners = array(); } private function a() { echo 'something'; } private function b() { echo 'something else'; } public function __call($fname, $args) { call_user_func_array(array($this, $fname), $args); foreach($this->listeners as $listener) { $listener->notify('fname was called'); } } public function addListener(Listener $listener) { $this->listeners[]= $listener; } } 

.

  class Listener { public function notify($message) { echo $message; } } 

Example:

  $t = new Test(); $l = new Listener(); $t->addListener($l); $t->a(); 
+10
source

This is the classic challenge for aspect-oriented programming (AOP). PHP does not have built-in AOP support, however there are some frameworks that make AOP possible in PHP. One of them is GO! AOP PHP framework . You can also implement AOP using runkit .

+3
source

You need for PHP SplObserver: From PHP Doc

0
source

This is a classic task for dependency injection and lazy initialization! Dependency is a MySQL connection. Since it must first be available when the first request is executed, it does not need to be initialized at startup, but only then. This is called lazy initialization, and its implementation is extremely simple:

 class DbStuff { private $__conn = NULL; protected function _getConn() { if ( is_null( $this->__conn ) { $this->__conn = ... ; // init (MySQL) DB connection here // throw on errors! } return $this->__conn; } public function someQuery($arg1, $arg2) { $conn = $this->_getConn(); // MySQL query here: ... } } 

The required "refactoring" requires calling $this->_getConn() in each request method.

Aspect-oriented programming is not a tool to solve this problem, since connecting to the database is an inherent dependence of the request, and not its aspect. An automatic log of all executed queries was an aspect.

A trigger built around PHP __call() is also not a good choice; besides the fact that they knock out modern IDE checks - which look great fast, whether the module is in order - this would unnecessarily complicate the tests: protected $this->_getWhatever() can be easily overwritten in the test facade object obtained from the class so that check - return the layout or something else. With __call() , more code is required for the same purpose, which causes a risk of errors in the code, which exists only for testing (and should be absolutely free from errors)

0
source

Source: https://habr.com/ru/post/1484447/


All Articles