开发者

PHP: How to realize event handler?

I want to add custom event handler to object's method.

I've got a class with method.

class Post {

    public function Add($title) {

        // beforeAdd event should be called here

        echo 'Post "' . $title . '" added.';
        return;
    }
}

I want to add an event to method Add and pass method's argument(s) to the event handler.

function AddEventHandler($event, $han开发者_运维问答dler){
    // What should this function do?
}

$handler = function($title){
    return strtoupper($title);
}

AddEventHandler('beforeAdd', $handler);

Is it possible to do something like this? Hope my question is clear.


Should be pretty easy using the functions defined here http://www.php.net/manual/en/book.funchand.php

In particular you should keep an handler array (or array of arrays if you want multiple handlers for the same event) and then just do something like

function AddEventHandler($event, $handler){
    $handlerArray[$event] = $handler;
}

or

function AddEventHandler($event, $handler){
    $handlerArray[$event][] = $handler;
}

in case of multiple handlers.

Invoking the handlers then would be just matter of calling "call_user_func" (eventually in a cycle if multiple handlers are needed)


Well, if you are using < php 5.3 then you cannot create a closure in such a way, but you can come close with create_function(); This would be

$handler = create_function('$title', 'return strtoupper($title);');

Then you store $handler in the class and you can call it as you desire.


Methods

You have multiple methods how to do it described by ircmaxell here.

And here is ToroHook used in ToroPHP (Routing lib).

Hook

class ToroHook {
    private static $instance;
    private $hooks = array();

    private function __construct() {}
    private function __clone() {}

    public static function add($hook_name, $fn){
        $instance = self::get_instance();
        $instance->hooks[$hook_name][] = $fn;
    }

    public static function fire($hook_name, $params = null){
        $instance = self::get_instance();
        if (isset($instance->hooks[$hook_name])) {
            foreach ($instance->hooks[$hook_name] as $fn) {
                call_user_func_array($fn, array(&$params));
            }
        }
    }
    public static function remove($hook_name){
        $instance = self::get_instance();
        unset($instance->hooks[$hook_name]);
        var_dump($instance->hooks);
    }
    public static function get_instance(){
        if (empty(self::$instance)) {
            self::$instance = new Hook();
        }
        return self::$instance;
    }
}

Using hook

It is simple call it like this:

ToroHook::add('404', function($errorpage){
    render("page/not_found", array("errorpage" => $errorpage));
});


Take look on my sphido/events library:

  • it's easy to use (few lines of code)
  • based on PHP Function handling
  • allow prioritising listeners
  • add/remove listeners
  • filter values by functions
  • stop propagation in function chain
  • add default handler

Event handler example

on('event', function () {
  echo "wow it's works yeah!";
});

fire('event'); // print wow it's works yeah!

Filter function example

add_filter('price', function($price) {
  return (int)$price . ' USD';
});

echo filter('price', 100); // print 100 USD
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜