PHP 在 5.3引入了匿名函数closure的概念,这个也就是俗称的闭包,指的是包含有未绑定到特定对象的变量(自由变量)的代码块
创建closure对象:
1 2 3
| $foo = function(){ }; $foo();
|
闭包声明参数以及调用外部变量:
1 2 3 4 5 6
| $value = 'hello'; $foo = function($bar) use ($value){ echo $value . $bar; }; $foo('world');
|
使用引用和不使用引用,根据官方文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php $result = 0;
$one = function() { var_dump($result); };
$two = function() use ($result) { var_dump($result); };
$three = function() use (&$result) { var_dump($result); };
$result++;
$one(); $two(); $three(); ?>
|
不使用引用时,在闭包内部的$result实际是声明时候对外部变量$result的复制,因此闭包内部对$result的处理不会影响到外部变量result,而使用引用则闭包内$result直接指向外部变量$result的内存地址,因此会对外部$result造成影响:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?php $x = 0; $foo = function() use ($x){ $x++; echo $x; };
$bar = function() use (&$x){ $x++; echo $x; }; $foo(); $foo(); $bar(); $bar();
?>
|
因为闭包的存在,我们便可以在不需要在外部声明回调函数的情况下使用一些类似于array_walk的方法,比如官方手册中提供的购物车的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <?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";
?>
|