PHP的匿名函数和闭包
一:匿名函数
1:匿名函数就是没有名字的函数
<?php $id = 100; $name = function($str) use($id){ //use可以引入外部变量,这里把$id传进来,如果不需要外部变量,则不加use return $str.$id; }; //匿名函数要带结束符 echo $name('lijie');
2:preg_replace_callback和匿名函数结合
<?php //这是一个正则,把$string 里的int 找出来加10,替换 $string = "Some numbers: one: 1; two: 2; three: 3 end"; $ten = 10; $newstring = preg_replace_callback( '/(\\d+)/', function($match) use ($ten) {return (($match[0] + $ten)); }, //$match为每次匹配得到的数据 $string //原数据,从这里匹配 ); echo $newstring; //这里为什么要用匿名函数有两个原因 //1:没必要单独为preg_replace_callback命令一个函数 //2:如果有外部变量,可以通过use传值
3:再看一个回调函数中的使用:
<?php $arr = ['1'=>'t1','2'=>'t2','3'=>'t3']; $new = array_map(function($v){ return $v.' - abc'; },$arr); //通过匿名函数回调,这里$arr数组有三个元素,回调三次;当然也可以通过foreach实现 print_r($new);如果不用匿名函数,则传统的写法:
<?php $arr = ['1'=>'t1','2'=>'t2','3'=>'t3']; $new = array_map("cube", $arr); //如果不通过匿名函数,则下面这种写法 function cube($str) { return $v.' - abc'; } print_r($new);
二:闭包
函数中包含子函数,子函数继承父函数的变量,这就是闭包,子函数调用父函数的局部变量用关键字 use
以下例子:将匿名函数在普通函数中当做参数传入,也可以被返回。
<?php function add($a) //普通函数add { $abAdd = function ($b=2) use($a) { //匿名函数,如果不加use,匿名函数无法调用add函数中的变量 return $a+$b; //如果不加use,这里就无法调取$a }; return $abAdd; //返回这个匿名函数 } $abAdd = add(21); //这里add是返回的一个对象 echo $abAdd(6);//调用匿名函数
上面功能好像没什么吸引力,再看一个例子,一个简单的容器:
<?php class Di { private $factory; public function set($id, $value) { $this->factory[$id] = $value; } public function get($id) { $val = $this->factory[$id]; return $val();//如果不加括号,仅仅返回的是闭包类,并不是User实例 } } class User { private $username; public function __construct($username = '') { $this->username = $username; } public function getUserName() { return $this->username; } } $di = new Di(); // 注册,在此使用了闭包,所以实际上并不会实例化User类,只有在后面get的时候才会实例化 $di->set('a', function(){ return new User('张三'); }); $a = $di->get('a'); //获取服务,相当于实例化 echo $a->getUserName();Di容器用来保存对象实例,set()方法注册到容器,然后通过get获取,set的时候不会真的实例化,只有在get的时候才实例化,这样实现了按需加载,而通过容器也便于统一管理。