PHP的闭包(Closure)也便是匿名函数
是PHP5.3引入的。

闭包的语法很大略, 须要把稳的关键字就只有use, use意思是连接闭包和外界变量。

匿名函数中的use, 其浸染便是从父浸染域继续变量。

phpfunctionusePHP 闭包匿名函数中的use用法 Angular

下例是最常见的用法, 如果不该用use, 匿名函数中将找不到变量$msg

<?php$msg = [1,2,3];$func = function()use($msg){ print_r($msg);};$func();?>

运行输出

Array([0] => 1[1] => 2[2] => 3)

关于继续变量的机遇

继续变量的行为是在函数定义时产生还是在函数调用时产生? 我们调度下上例中代码的顺序, 将$msg置于函数定义之后

<?php$func = function()use($msg){ print_r($msg);};$msg = [1,2,3];$func();?>

运行输出

PHP Notice: Undefined variable: msg in /search/ballqiu/c.php on line 4

可见, 继续变量的行为是在函数定义时产生的。
上例中定义msg, 以是函数运行时$msg便是未定义变量。

办理方法: 利用引用传值

<?php$func = function()use(&$msg){print_r($msg);};$msg = [1,2,3];$func();?>

关于use中利用引用传值

我们知道, 在匿名函数的use中如果利用引用传值, 那么匿名函数中对参数值的改变会同样影响外部相应变量。
比如下面的例子:

<?php$msg = [1,2,3];$func = function()use(&$msg){$msg[0]++;print_r($msg);};$func();print_r($msg);?>

运行输出

Array([0] => 2[1] => 2[2] => 3)Array([0] => 2[1] => 2[2] => 3)

那么是不是任何情形下, 想通过匿名函数改变外部变量值都一定要通过引用办法向use传值呢? 看下面这个例子:

<?php$msg = new ArrayObject([1,2,3], ArrayObject::ARRAY_AS_PROPS);$func = function()use($msg){ $msg[0]++; print_r($msg);};$func();print_r($msg);?>

运行输出

ArrayObject Object([storage:ArrayObject:private] => Array([0] => 2[1] => 2[2] => 3))ArrayObject Object([storage:ArrayObject:private] => Array([0] => 2[1] => 2[2] => 3))

可见, 如果通报object类型的变量, 纵然不显示利用引用通报, 匿名函数中变量值的改变同样会影响到外部干系变量。

但是, 问题又来了。
向use通报object变量时, 利用引用与不该用引用到底有没有差异呢? 还是来看例子

$func = function()use($msg){echo $msg[0],"\n";};$msg = new ArrayObject([1,2,3], ArrayObject::ARRAY_AS_PROPS);$func();?>

运行输出

PHP Notice: Undefined variable: msg

我们改为利用引用通报

$func = function()use(&$msg){echo $msg[0],"\n";};

运行输出

1

可见利用引用通报时, 纵然变量滞后于函数定义, 函数内部还是可以找到外部相应的变量, 不会涌现变量未定义的情形。
两者还是有差异的。

关于class中匿名函数里的this及use

class C{protected $_num = 0;public function mkFunc(){$func = function(){echo $this->_num++, "\n";};return $func;}public function get(){echo $this->_num,"\n";}}$obj = new C();$func = $obj->mkFunc();$func();$obj->get();?>

运行结果

01

可见匿名函数里的this便是指当前工具, 不须要利用use就可以直接找到。

还是上面的例子, 如果一定要利用use会是什么效果呢?

将mkFunc改为

public function mkFunc(){//唯一改动是此处加了use$func = function()use($this){echo $this->_num++, "\n";};return $func;}

运行输出

PHP Fatal error: Cannot use $this as lexical variable

修正为

public function mkFunc(){$self = $this;$func = function()use($self){echo $this->_num++, "\n";};return $func;}

运行结果

01

可见是否利用use, 效果是一样的。

闭包用场

购物车功能

在此例子中, 通过匿名函数和闭包实现了一个"钩子"或者叫回调函数, 在调用getTotal()函数时, 实现了$callback的匿名函数, 使得打算总额变得相称轻松和随意马虎。

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);// 打出出总价格,个中有 5% 的发卖税.print $my_cart->getTotal(0.05) . "\n";// 末了结果是 54.29

那么闭包又有什么用或者说有什么好处?

从上面的例子中可以看出, 利用闭包可以很随意马虎的实现我们常说的"钩子"。

通过闭包,在搭配array_walk()和array_map()等函数利用时相称清爽

$users = array("Wenzhi", "Qmn",);array_walk($users, function ($name) {echo "Hello $name<br>";});