###概述 闭包和匿名函数在PHP 5.3.0中引入,这两个特性非常有用,每个PHP开发者都应该掌握。 闭包是指在创建时封装周围状态的函数,即使闭包所在的环境的不存在了,闭包中封装的状态依然存在。 匿名函数其实就是没有名称的函数,匿名函数可以赋值给变量,还能像其他任何PHP函数对象那样传递。不过匿名函数仍然是函数,因此可以调用,还可以传入参数,适合作为函数或方法的回调。 注:理论上讲闭包和匿名函数是不同的概念,不过PHP将其视作相同的概念(匿名函数在PHP中也叫作闭包函数),所以下面提到闭包时指的也是匿名函数;反之亦然。 ###匿名函数 ```php <?php $greet = function ($name) { return sprintf("Hello %s\r\n", $name); }; echo $greet('匿名函数'); ``` ###闭包 闭包和普通的PHP函数很像:常用的句法相同,也接受参数,而且能返回值。不过闭包没有函数名。 - 函数里定义一个匿名函数,并且调用它 ```php function content(){ $func = function($param){ echo $param; }; $func('hello world'); } content(); ``` - 函数中把匿名函数返回,返回后调用它 ```php function content(){ return $func = function($param){ echo $param; }; } $data = content(); $data('hello world'); ``` - 把匿名函数当做参数传递,并且调用它 ```php function callFunc($func){ $func('hello world'); } $data = function($param){ echo $param; }; callFunc($data); ``` - 直接将匿名函数进行传递 ```php function callFunc($func){ $func('hello world'); } callFunc(function($param){ echo $param; }); ``` ###连接闭包和外界变量的关键字:use 闭包可以保存所在代码块上下文的一些变量和值。PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。 ```php function getMoney() { $rmb = 1; $dollar = 8; $func = function() use ( $rmb,$dollar) { echo $rmb; echo $dollar; }; $func(); } getMoney(); ``` > use所引用的也只不过是变量的一个副本clone而已,所以如果想要完全引用变量,要用`&` ```php function getMoney() { $rmb = 1; $func = function() use ( &$rmb ) { echo $rmb.'<br>'; //把$rmb的值加1 $rmb++; }; $func(); echo $rmb; } getMoney(); ``` ###将匿名函数绑定到类中 闭包是一个对象,所以可以在闭包中使用$this关键字获取闭包的内部状态,需要用到closure类。 ```php Closure::__construct — 用于禁止实例化的构造函数 Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域 Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域 ``` ###bindTo ```php 参数1 :传类进去,public属性和方法.只传第1个参数即可 参数2 :传类进去,private或protected属性和方法.就要传第2个参数.两种写法:(1)传类名,直接字符串 (2)传类当前对象[第一个参数相同的$obj],bindTo()会自动获取类名 ``` ###bind() ```php 参数1($closure) :表示闭包函数 参数2($newthis) :相当于在函数内/外调用的区别,传类的实例表示在内部调用,NULL相当于在外部调用 参数3($newscope) :相当于类和实例调用的区别,函数的作用域,传类表示静态调用方式,内部可以“类名::属性”的方式使用;实例表示实例调用方式,内部可以“->” ``` ###获取类中属性(通过匿名函数获取) ```php class User{ private $name ; function __construct ( $name ){ $this ->name = $name ; } } $func = function () { return "Hello " . $this ->name; }; $obj = new User('admin'); $dataUser = $func->bindTo($obj,'User'); echo $dataUser(); 或者 $dataObj = $func->bindTo($obj,$obj); echo $dataObj(); ``` ```php class Animal { private static $cat = "cat"; private $dog = "dog"; public $pig = "pig"; } /* * 获取Animal类静态私有成员属性 */ $cat = static function() { return Animal::$cat; }; /* * 获取Animal实例私有成员属性 */ $dog = function() { return $this->dog; }; /* * 获取Animal实例公有成员属性 */ $pig = function() { return $this->pig; }; $bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象 $bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包 $bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域 echo $bindCat(),'<br>';// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性 echo $bindDog(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性 echo $bindPig(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性 ```