php callback (like jQuery)?
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');
精彩评论