💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] * * * * * ## 1 闭包(匿名)函数的意义 **闭包(匿名)函数通常作为简单函数功能的实现。** 闭包(匿名)函数可以**赋值给变量**,或者**作为参数使用**。 闭包(匿名)函数是**函数编程**的基础 ## 2 闭包(匿名)函数的使用 ### 2-1 匿名函数赋值给变量 ~~~ <?php $greet = function( $name ) { printf ( "Hello %s\r\n" , $name ); }; $greet ( 'World' ); $greet ( 'PHP' ); ?> ~~~ ### 2-2 匿名函数用作函数参数 ~~~ <?php echo preg_replace_callback ( '~-([a-z])~' , function ( $match ) { return strtoupper ( $match [ 1 ]); }, 'hello-world' ); ?> ~~~ 有没有jQuery的post()函数感觉?? ## 3 闭包函数的父作用域参数传递 ### 3-1 显式传递 作为function()的参数 ~~~ <?php $message = 'hello' ; $example = function ($message) { var_dump ( $message ); }; echo $example (); ?> ~~~ ### 3-2 隐式传递 使用use语言结构 ~~~ <?php $message = 'hello' ; $example = function () use ( $message ) { var_dump ( $message ); }; echo $example (); ?> ~~~ ### 3-3 引用参数 ~~~ <?php $message = 'hello' ; $example = function () use (& $message ) { var_dump ( $message ); }; echo $example (); ?> ~~~ ### 3-4 多参数传递 ~~~ <?php $message = 'world' ; $example = function ( $arg ) use ( $message ) { var_dump ( $arg . ' ' . $message ); }; $example ( "hello" ); ?> ~~~ ## 4 闭包函数的类作用域参数传递 闭包函数表达式在php底层实现为类\Closure的对象实例 **可以使用\Closure::bind()和$Closure->Bindto()** 修改闭包函数的参数和作用域为特定对象和类 ### 4-1 闭包对象方法: Closure::bindTo `public Closure Closure::bindTo ( object $newthis [, mixed $newscope = 'static' ] )` $newthis:参数对象 $newscope:参数作用域类 ~~~ <?php class A { function __construct ( $val ) { $this -> val = $val ; } function getClosure () { //returns closure bound to this object and scope return function() { return $this -> val ; }; } } $ob1 = new A ( 1 ); $ob2 = new A ( 2 ); $cl = $ob1 -> getClosure (); echo $cl (), "\n" ; $cl = $cl -> bindTo ( $ob2 ); echo $cl (), "\n" ; ?> ~~~ 输出: 1 2 ### 4-2 闭包类方法: Closure::bind `public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )` > $closure:需要修改的匿名函数对象 > $newthis:匿名函数的参数对象 > $newscope:匿名函数的参数类作用域 ~~~ <?php class A { private static $sfoo = 1 ; private $ifoo = 2 ; } $cl1 = static function() { return A :: $sfoo ; }; $cl2 = function() { return $this -> ifoo ; }; $bcl1 = Closure :: bind ( $cl1 , null , 'A' ); $bcl2 = Closure :: bind ( $cl2 , new A (), 'A' ); echo $bcl1 (), "\n" ; echo $bcl2 (), "\n" ; ?> ~~~ 以上例程的输出类似于: 1 2 >[info] 两种不同在于一个是对象方法,一个是类静态方法 ## 5 闭包函数的反射调用 闭包函数对象可以作为普通对象,使用反射api进行操作 如think\Route.php的Route::checkDomain() ~~~ if ($rule instanceof \Closure) { $reflect = new \ReflectionFunction($rule); self::$bind = $reflect->invokeArgs([]); return; } ~~~ ## 6 闭包函数的参数操作 ~~~ func_num_args() 获取参数个数 func_get_arg() 获取特定参数 func_get_args() 获取参数数组 ~~~ 类似于js的arguments用法 ## 7 闭包函数的使用实例 ### 7-1 类中使用闭包函数 ~~~ <?php class Cart { const PRICE_BUTTER = 1.00 ; const PRICE_MILK = 3.00 ; const PRICE_EGGS = 6.95 ; protected $products = array(); public function add ( $product , $quantity ) { $this -> products [ $product ] = $quantity ; } public function getQuantity ( $product ) { return isset( $this -> products [ $product ]) ? $this -> products [ $product ] : FALSE ; } public function getTotal ( $tax ) { $total = 0.00 ; $callback = function ( $quantity , $product ) use ( $tax , & $total ) { $pricePerItem = constant ( __CLASS__ . "::PRICE_" . strtoupper ( $product )); $total += ( $pricePerItem * $quantity ) * ( $tax + 1.0 ); }; array_walk ( $this -> products , $callback ); return round ( $total , 2 );; } } $my_cart = new Cart ; $my_cart -> add ( 'butter' , 1 ); $my_cart -> add ( 'milk' , 3 ); $my_cart -> add ( 'eggs' , 6 ); print $my_cart -> getTotal ( 0.05 ) . "\n" ; ?> ~~~ ## 8 函数编程进阶 ## 9 php的闭包函数与js闭包函数比较