обратный вызов php (как jQuery)? - PullRequest
4 голосов
/ 18 марта 2011

в jQuery вы можете написать что-то вроде


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

Мне было интересно, если вы можете сделать что-то подобное в php, не используя eval.

как то так?Я знаю, что это не сработает.


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

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

Кто-то из вас может спросить, зачем это нужно?Ну, я пытаюсь упростить мой код, не используя так много операторов if.


$act = new act;

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

Приведенный выше код позволит избежать использования нескольких операторов if.


$act = new act;

if( $act->bind('something') ) {
      // bind returned true so do this?
}

Я знаю, что вы могли быиспользуйте ob_get_contents для возврата уклоненного кода, но ewww.


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

return $evaled;

Ответы [ 5 ]

6 голосов
/ 18 марта 2011

Вы действительно можете определить обратный вызов функции (или методы) в PHP.

Это может быть реализовано с помощью:


Для нескольких примеров взгляните на раздел callback следующей страницы руководства: Псевдотипы и переменные, используемые в этой документации

5 голосов
/ 18 марта 2011
if($pref == 'something' ) {
        // return and perform actions in $callback?
        call_user_func($callback);
}

call_user_func делает то, что вы хотите, вы даже можете передавать аргументы

http://it.php.net/call_user_func

Пример

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

    call_user_func($func);
}

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

// prints: hellohello2
1 голос
/ 18 марта 2011

Другие ответы пока хороши, но, увидев, что ваш основной интерес к событиям, я покажу вам, как это сделать, вместе с цепочкой (бонус!).

/**
 * 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;
}

И вот пример:

// 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');
1 голос
/ 18 марта 2011

PHP 5.3 фактически добавил анонимные функции, так что вы можете в основном передать функцию в качестве аргумента другому вызову функции и выполнить ее оттуда.

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

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

$act->bind('test', $callback);
1 голос
/ 18 марта 2011

Если вы собираетесь передавать несколько аргументов в обратный вызов, используйте call_user_func_array, аналогично уже упомянутому call_user_func, за исключением того, что в качестве второго параметра он принимает массив аргументов.

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

Кроме того, вы можете передать анонимную функцию, а не имя функции.

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

Анонимная функция может быть передана как переменная, как в этом примере, или объявлена ​​непосредственно в качестве аргумента.

...