开发者

php callback (like jQuery)?

开发者 https://www.devze.com 2023-02-17 18:14 出处:网络
in jQuery you can write something like $(selector).bind(\'click\', function(e) { // something was true - do these actions.

in jQuery you can write something like


$(selector).bind('click', function(e) {
      // something was true - do these actions.
});

I was wondering if in php you could do something similar without using eval.

something like this? I know this wont work btw.


class act{
    public function bind($pref, $callback) {

       if($pref == 'something' ) {
             // return and perform actions in $callback?
             eval($callback);
       }
    }
}

Some of you might ask what the need for this is? Well I'm trying to simplify my code without using so many if statements.


$act = new act;

$act->bind('something', function(e) {
      echo 'this was the php code to run in the callback';
});

The above code would avoid using a bunch of if statements.


$act = new act;

if( $act->bind('something') ) {
      // bind returned true so do this?
开发者_如何学Go}

I know you could use ob_get_contents to return the evaled code, but ewww.


ob_start();
eval('?> ' . $callback . '<?php ');
$evaled = ob_get_contents();
ob_end_clean();

return $evaled;


You can indeed define callback functions (or methods) in PHP.

This can be implemented with either :

  • call_user_func() and other functions of its familly
  • Or anonymous functions, with PHP >= 5.3


For a couple examples, take a look at the callback section of the following manual page : Pseudo-types and variables used in this documentation


if($pref == 'something' ) {
        // return and perform actions in $callback?
        call_user_func($callback);
}

call_user_func does what you want, you can even pass arguments

http://it.php.net/call_user_func

EXAMPLE

function g($msg,$func){
    echo $msg;

    call_user_func($func);
}

g('hello',function (){echo 'hello2';});

// prints: hellohello2


If you're going to be passing multiple arguments to the callback, use call_user_func_array, similar to the already mentioned call_user_func except as a second parameter, it takes an array of arguments.

$functionName = 'foo';
$functionArgs = array('bar', 'baz');
call_user_func_array($functionName, $functionArgs);

Alternatively, you can pass an anonymous function, rather than the function name.

$functionBody = function($arg1, $arg2){
        echo $arg1 . $arg2;
    };
$functionArgs = array('bar', 'baz');
call_user_func_array($functionBody, $functionArgs);

The anonymous function can be passed as a variable like in this example, or declared directly inline as the argument.


PHP 5.3 actually added anonymous functions so you can basically pass a function as argument to another function call and execute it from there.

http://php.net/manual/en/functions.anonymous.php

$callback = function($name){
    printf("Hello %s\r\n", $name);
};

$act->bind('test', $callback);


The other answers are great so far, but seeing that your main interest is in events, I'll show you how to do it, together with chaining (bonus!).

/**
 * jQuery events+chaining prototype.
 */
class pQuery {

    /// PROTECTED PROPERTIES ///

    /**
     * @var array Holds list of event=>callbacks items.
     */
    protected $events=array();

    /// PROTECTED UTILITY METHODS ///

    /**
     * Creates an anonymous function compatible with PHP 4+.
     * <b>IMPORTANT</b> It is likely functions made this way are not garbage collected.
     * @param $funcCode string Function decleration, including the body.
     * @return string The newly created function's name.
     */
    protected static function mk_anonFunc($funcCode){
        static $counter=0;
        $func='pQanon'.(++$counter);
        @eval('function '.$func.'('.substr($funcCode,9));
        if(!function_exists($func))
            die('Fatal: Anonymous function creation failed!');
        return $func;
    }

    /**
     * Detects whether a string contains an anonymous function or not.
     * @param $funcCode string Function decleration, including the body.
     * @return boolean True if it does contain an anonymous function, false otherwise.
     */
    protected static function is_anonFunc($funcCode){
        return strpos($funcCode,'function(')!==false;
    }

    /// PUBLIC METHODS ///

    /**
     * Bind event callback to this jQuery instance.
     * @param string $event The event name, eg: 'click'.
     * @param string|array $callback A function or a class/instance method, eg: 
     *        'myFunc' OR array('myClass','myMtd') OR array($obj,'myMtd'). 
     * @return pQuery Chaining.
     */
    public function bind($event,$callback){
        if(self::is_anonFunc($callback))
            $callback=self::mk_anonFunc($callback);
        if(!isset($this->events[$event]))
            $this->events[$event]=array();
        $this->events[$event][]=$callback;
        return $this;
    }
    /**
     * Unbind event callback from this jQuery instance.
     * @param string $event The event name, eg: 'click'.
     * @param string|array $callback A function or a class/instance method, eg: 
     *        'myFunc' OR array('myClass','myMtd') OR array($obj,'myMtd'). 
     * @return pQuery Chaining.
     */
    public function unbind($event,$callback){
        if(!isset($this->events[$event])){
            if(($pos=array_search($callback,$this->events[$event]))!==false)
                unset($this->events[$event][$pos]);
        }
        return $this;
    }
    /**
     * Trigger event, calling all related callbacks.
     * @param string $event The event name to trigger, eg: 'click'.
     * @param array $params Optional array of arguments to pass to callback.
     * @return pQuery Chaining.
     */
    public function trigger($event,$params=array()){
        if(isset($this->events[$event]))
            foreach($this->events[$event] as $callback)
                call_user_func_array($callback,$params);
        return $this;
    }
}

/**
 * Allows us to use factory-singleton pattern.
 * @return pQuery The $pQuery instance.
 */
function pQuery(){
    global $pQuery;
    if(!isset($pQuery))
        $pQuery=new pQuery();
    return $pQuery;
}

And here goes an example:

// instantiate pQuery
// Note: to use it like jQuery does, do it as follows
// and then simply use "global $pQuery;" wherever you want it.
$pQuery = new pQuery();

// declare some sample callbacks
function start(){ echo 'start'; }
function stop(){ echo 'stop'; }

// bind some stuff and call start
$pQuery->bind('start','start')
       ->bind('stop','stop')
       ->trigger('start');

// bind more stuff and call click
$pQuery->bind('click','function(){ echo "clicked"; }')
       ->bind('custom','function(){ echo "custom"; }')
       ->bind('click','function(){ echo "clicked2"; }')
       ->trigger('click',array($pQuery,'arg2','arg3'));

// call end
$pQuery->trigger('stop');
0

精彩评论

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