PHP 闭包(Closure)

2020-02-19 23:15:24

参考地址 PHP 闭包(Closure)


一、闭包基本用法

闭包(Closure)又叫做匿名函数,也就是没有定义名字的函数。比如下面的例子:


// 定义一个闭包,并把它赋给变量 $f

$f = function () {

    return 7;

}


// 使用闭包也很简单

$f(); //这样就调用了闭包,输出 7


// 当然更多的时候是把闭包作为参数(回调函数)传递给函数

function testClosure (Closure $callback) {

    return $callback();

}


// $f 作为参数传递给函数 testClosure,如果是普遍函数是没有办法作为testClosure的参数的

testClosure($f);


// 也可以直接将定义的闭包作为参数传递,而不用提前赋给变量

testClosure (function () {

    return 7;

});


// 闭包不止可以做函数的参数,也可以作为函数的返回值

function getClosure () {

    return function () { return 7; };

}


$c = getClosure(); // 函数返回的闭包就复制给 $c 了

$c(); // 调用闭包,返回 7

二、闭包类(Closure)

定义一个闭包函数,其实是产生了一个闭包类(Closure)的对象,Closure 类摘要如下:


Closure {   

    public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])  

    public Closure bindTo (object $newthis [, mixed $newscope = 'static' ])  

方法说明:

Closure::bind: 复制一个闭包,绑定指定的 $this 对象和类作用域。

Closure::bindTo: 复制当前闭包对象,绑定指定的 $this 对象和类作用域。

下面将介绍 Closure::bind 和 Closure::bindTo

参数和返回值说明:

closure:表示需要绑定的闭包对象。

newthis:表示需要绑定到闭包对象的对象,或者 NULL 创建未绑定的闭包。

newscope:表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是'static', 表示不改变。

该方法成功时返回一个新的 Closure 对象,失败时返回 FALSE。


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实例公有成员属性


// bindTo与bind类似,是面向对象的调用方式,这里只举一个,其他类比就可以

$bindCat = $cat->bindTo(null, 'Animal');

最后举一个 PHP 官网给出的例子


class A {

    function __construct($val) {

        $this->val = $val;

    }

    function getClosure() {

        //returns closure bound to this object and scope

        return function() { return $this->val; };

    }

}


$ob1 = new A(1);

$ob2 = new A(2);


$cl = $ob1->getClosure();

echo $cl(), "\n";

$cl = $cl->bindTo($ob2);

echo $cl(), "\n";

以上示例输出:


1

2



  • 2019-12-18 23:26:00

    FFMPEG命令记录

    ffmpeg,拼接两个音频,剪切音频片段,多个音频混音,剪切一段MP4并转换成gif,改变音量大小,音频淡入淡出,音频格式处理

  • 2019-12-19 00:04:44

    ffmpeg concat video and mix audio

    在ffmpeg中,官网给出两种连接媒体文件(音频、视频、etc..)的解决方案。 the concat "demuxer" the concat "protocol" 对比而言, demuxer更加灵活一些,需要媒体文件是属于相同的编解码器,但是可以属于不同的容器格式(mp3,wav, mp4, mov, etc..). 而protocol只适用于少数集中容器格式。

  • 2019-12-19 00:16:30

    android采用FFmpeg实现音频混合与拼接剪切

    接触FFmpeg有一段时间了,它是音视频开发的开源库,几乎其他所有播放器、直播平台都基于FFmpeg进行二次开发。本篇文章来总结下采用FFmpeg进行音频处理:音频混合、音频剪切、音频拼接与音频转码。

  • 2019-12-19 15:01:58

    spring boot 在Linux下服务启动报错Unable to find Java

    将 Spring boot 安装为 Linux 服务启动,后输入 service myapp start 报错 Unable to find Java ,但是使用 java -jar myapp.jar 启动成功。不知道为啥引起的,经过百度找到下面这个解决方法和我的情况一样,终于把问题解决

  • 2019-12-19 16:44:01

    根据条件配置多个npm仓库

    scope 是一种很好的包管理方式。统一的“命名空间”,清晰、好辨识;在 registry 中使用统一的 organization 管理,不必担心命名冲突和冒用等。 在实际使用中,一个常见的场景是公司的私有仓库。使用统一的 scope 定义在私有仓库中定义私有包,绝对是一个非常好的方式。 指定 scope 从指定仓库安装