详解php中的闭包

php5.3有一个非常赞的新特性,那就是支持匿名函数(闭包)。匿名函数可用于动态创建函数,并保存到一个变量中。

举个栗子:

$func = function()
{
    exit('Hello world!!');
}; //这里必须要有;结尾

$func();

等效于

function func()
{
    exit('Hello world!!');
}

func();

看上去没什么新奇的地方是不?(☆_☆)/~~

别急,继续看。

看这段代码:

function operate($operator)
{
    if($operator == "-")
    {
        return function($a,$b)
        {
            return $a-$b;
        };
    }
    else
    {
        return function($a,$b)
        {
            return $a+$b;
        };
    }
}

$subtraction = operate("-");
echo $subtraction(4,3); //1
$addition = operate("+");
echo $addition(1,2); //3

通过operate函数,我们可以生成不同的函数作为结果返回,并将这个结果直接作为函数调用,上面的代码分别动态创建了减法运算和加法运算函数。


如果说仅仅是这样的话,那么我并不觉得它有多少吸引力,下面我将展示一个实战中用到的技巧:

<?php
header("Content-Type:text/html;charset=utf-8");
class Di
{
    private $_factory;
    
    public function set($id,$value)
    {
        $this->_factory[$id] = $value;
    }
    
    public function get($id)
    {
        $value = $this->_factory[$id];
        return $value();
    }
}

class User
{
    private $_username;
    
    function __construct($username="") 
    {
        $this->_username = $username;
    }
    
    function getUserName()
    {
        return $this->_username;
    }
}

//从这里开始看
$di = new Di();
$di->set("zhangsan",function(){
    return new User('张三');
});

$di->set("lisi",function(){
   return new User("李四"); 
});

echo $di->get("zhangsan")->getUserName();
echo $di->get("lisi")->getUserName();

代码中有一个Di容器用来保存对象实例,然后通过set()方法注册服务,通过get()方法获取服务。

我们看到$di->set()的时候,使用了匿名函数,我们预先注册了zhangsan和lisi两个服务,这两个服务都是User类的实例,在$di->set的时候实际上并没有实例化,而是在$di->get()的时候才执行了匿名函数并将对象返回,这就实现了按需实例化,不用则不实例化,提高效率。

闭包特性:

经常写js的同学应该知道js的闭包特性,简单的说就是在一个函数里可以定义子函数,父函数中的变量在子函数中可以直接使用,那么PHP的闭包怎么用呢?有一点区别。

function func1($a)
{
    return function() use ($a)
    {
        echo $a;
    };
}

$a = func1("a");

$a();//输出a

当你想将外层变量传进内层匿名函数时,使用use (变量)的方式。


闭包的用途可以用于很多地方,常见于DI模式中,这篇文章的代码只是为了说明,不可以直接使用,谢谢。

连接闭包和外界变量的关键字:use


注意:使用闭包方式获取函数外部变量的时候,如果在闭包中改变了变量的值,出了闭包函数后,在输出 该变量的值,发现虽然在闭包函数中被改变了,但是出了闭包外面 变量又恢复成了原本的值 举个栗子:

$variable = 10;

$callback = function() use($variable){

    echo ++$variable."<br/>";
};

$callback();  //输出:11

echo $variable; //输出:10

啊,原来use所引用的也只不过是变量的一个副本(拷贝)而已。由此可见 默认这是传值的方式。如果在闭包中修改了变量也能直接影响到闭包外面,那么我们在闭包中引用(加 & 符号)该变量即可。 即 引用闭包外该变量的地址。还是上面那个栗子:

$variable = 10;

$callback = function() use(&$variable){

    echo ++$variable."<br/>"; //注意:我们这里是用的引用(&)方式
};

$callback();  //输出:11

echo $variable; //输出:11


搞定。结束。


浮生潦草闲愁广,一听啤酒一口尽。



参考链接:https://www.cnblogs.com/hellowzd/p/5888505.html

                https://www.cnblogs.com/clphp/p/5147369.html

声明:禁止任何非法用途使用,凡因违规使用而引起的任何法律纠纷,本站概不负责。

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

精彩评论

全部回复12人评论7,777人参与