回调函数:通俗的解释就是把函数作为参数传入进另一个函数中使用;PHP中有许“需求参数为函数”的函数,像array_map,usort,call_user_func_array之类,他们执行传入的函数,然后直接将结果返回主函数。好处是函数作为值使用起来方便,而且代码简洁,可读性强。
匿名函数,即没有一个确定函数名的函数,只能在创建时调用或做参数使用。
闭包,是一种对作用域进行封装的方式,使得函数能使用父作用域中的变量。
回调的作用:利用回调,可以在运行时将与组件的核心任务没有直接关系的功能插入到组件中。有了组件回调,你就赋予了他人在你不知道的上下文中扩展你的代码的权力。
<?php
/*
回调、匿名函数和闭包
2018.9.16
*/
class Product{
public $name;
public $price;
function __construct( $name, $price ) {
$this->name = $name;
$this->price = $price;
}
}
class ProcessSale {
private $callbacks;
function registerCallback( $callback) {
if( !is_callable( $callback)){//检测参数是否为合法的可调用结构,测试此函数是否可以被调用
throw new Exception( "callback not callable" );
}
$this->callbacks[] = $callback;//这里为什么用数组来存储?????????????????????????????????????????//
}
function sale( $product ) {
print "{$product->name}:processing \n\n";
echo "\n";
foreach ( $this->callbacks as $callback ) {
call_user_func( $callback, $product);
//通过第一个参数,来调用用户自己的函数
}
}
}
class Mailier {
function doMail ( $product ) {
print " mailing ({$product->name})\n";
}
}
class Totalizer {
static function warnAmount( $amt) {
$count = 0;
return function ( $product ) use ( $amt, &$count) {//$count可以用引用来访问
$count += $product->price;
print " count:$count\n";
if( $count > $amt ){
print " high price reached:{$count }\n";
}
};
}
}
//create_function()创建匿名函数
//$logger = create_function( '$product', 'print " logging({$product->name})\n";');
//另一种创建匿名函数的方法(推荐使用)
$logger = function( $product ) {
print " logging({$product->name})\n";
};
//$processor = new ProcessSale();
//$processor->registerCallback( $logger );
//回调可以使用函数名甚至是对象引用和方法
//$processor = new ProcessSale();
//$processor->registerCallback( array( new Mailier(), "doMail") );//数组形式的回调以对象做为其第一个元素,以方法名作为其第二单位元素
//use可以让匿名函数追踪来自其父作用域的变量
$processor = new ProcessSale();
$processor->registerCallback(Totalizer::warnAmount(8));
$processor->sale( new Product( "shoes", 6 ) );
print "\n";
$processor->sale( new Product( "coffee", 6) );
?>