一、概述

https://www.php.net/manual/zh/class.closure.php

闭包是指在创建时封装周围状态的函数,即使闭包所在的环境的不存在了,闭包中封装的状态依然存在。
闭包对象实现了__invoke()魔术方法,只要变量名后有(),PHP就会查找并调用__invoke方法。

1、闭包可以赋值给变量
2、闭包可以作为参数(回调函数)传递给函数
3、闭包可以作为函数的返回值
4、定义一个闭包函数,即产生了一个闭包类(Closure)的对象

Closure {
/* Methods */
private __construct ( void ) /**
* Closure::bindTo的静态版本
*/
public static bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] ) : Closure /**
* 复制当前闭包对象,绑定指定的$this对象和类作用域。
*/
public bindTo ( object $newthis [, mixed $newscope = "static" ] ) : Closure /**
* 绑定闭包对象到$newthis,并使用参数$parameters进行调用
*/
public call ( object $newthis [, mixed $... ] ) : mixed /**
* 将一个callable对象转换成一个闭包对象
*/
public static fromCallable ( callable $callable ) : Closure
}

方法说明:

Closure::bind: 复制一个闭包,绑定指定的 $this 对象和类作用域。是 Closure::bindTo() 的静态版本。
Closure::bindTo: 复制当前闭包对象,绑定指定的 $this 对象和类作用域。

call()fromCallable()是从PHP 7.0以后新增的。

bind参数和返回值说明:
closure:表示需要绑定的闭包对象。
newthis:表示需要绑定到闭包对象的对象,或者 NULL 创建未绑定的闭包。
newscope:表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是'static', 表示不改变。类作用域用来决定在闭包中 $this 对象的 私有、保护方法 的可见性
该方法成功时返回一个新的 Closure 对象,失败时返回 FALSE。

bindTo参数和返回值说明:
newthis:表示需要绑定到闭包对象的对象,或者 NULL 创建未绑定的闭包。
newscope:表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是'static', 表示不改变。

使用:

Closure类的bindTo()bind()方法提供了将一个闭包绑定到一个类对象的功能

<?php

class Animal {
private static $cat = "cat";
private $dog = "dog";
public $pig = "pig"; public function say(string $param)
{
return 'hello '. $param;
}
} /*
* 获取Animal类静态私有成员属性
*/
$cat = static function() {
return Animal::$cat;
}; /*
* 获取Animal实例私有成员属性
*/
$dog = function() {
return $this->dog;
}; /*
* 获取Animal实例公有成员属性
*/
$pig = function() {
return $this->say($this->pig);
}; // 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象,因此不能使用$this对象
$bindCat = Closure::bind($cat, null, new Animal());
// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包,因此可以访问非公有的属性和方法
$bindDog = Closure::bind($dog, new Animal(), 'Animal');
// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域,因此只能调用公有的属性和方法
$bindPig = Closure::bind($pig, new Animal());
// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性,若没有作用域,则只能访问公有的
echo $bindCat(),'<br>'; // cat
// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例所有的成员属性和方法
echo $bindDog(),'<br>'; // dog
// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性和方法
echo $bindPig(),'<br>'; // hello pig // bindTo与bind类似,bind是bindTo的静态版本,这里只举一个,其他类比就可以
$bindCat = $cat->bindTo(null, 'Animal');
echo $bindCat(); // cat

官方实例

<?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"; // 1
$cl = $cl->bindTo($ob2);
echo $cl(), "\n"; // 2

call 绑定闭包对象到$newthis,并使用参数$parameters进行调用

<?php
class Value {
protected $value; public function __construct($value) {
$this->value = $value;
} public function getValue() {
return $this->value;
}
} $three = new Value(3);
$four = new Value(4); $closure = function ($delta) { var_dump($this->getValue() + $delta); };
$closure->call($three, 4); //
$closure->call($four, 4); //

 二、综合实例

<?php

class A
{
public $a; public function __construct($a)
{
$this->a = $a;
} public function getValue()
{
return $this->a;
}
} function say($world = 'hello world!')
{
return $world;
} function say2()
{
return $this->getValue();
} $say3 = function () {
return $this->getValue();
}; $obj = new A('aaa'); // 转为闭包对象
$say1 = Closure::fromCallable('say');
$func1 = $say1->bindTo($obj);
echo $func1(), '<br>'; // hello world! // 将函数转为闭包
$say2 = Closure::fromCallable('say2');
$func2 = $say2->bindTo($obj);
echo $func2(), '<br>'; // aaa // 绑定闭包对象到$obj,并进行调用
echo $say3->call($obj),'<br>'; // aaa // 使用bind的静态版本
$func3 = Closure::bind($say3, $obj);
echo $func3(); // aaa

现代 PHP 新特性 —— 闭包的更多相关文章

  1. ES6 新特性

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...

  2. PHP的学习--新特性

    最近做的项目使用了 php7,但感觉有很多新特性没有用起来.就想总结一下,一些可能会用到的新特性.之前使用的环境是 php5.4,所有也会有 php5.5 和 php5.6 的特性总结进来,这里只列出 ...

  3. Swift3新特性汇总

    之前 Apple 在 WWDC 上已将 Swift 3 整合进了 Xcode 8 beta 中,而本月苹果发布了 Swift 3 的正式版.这也是自 2015 年底Apple开源Swift之后,首个发 ...

  4. Java 8新特性终极指南

    目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展 ...

  5. php5.3到php7.0.x新特性介绍

    <?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...

  6. Java8的新特性以及与C#的比较

    函数式接口 VS 委托 在C中,可以使用函数指针来存储函数的入口,从而使得函数可以像变量一样赋值.传递和存储,使得函数的调用变得十分灵活,是实现函数回调的基础.然而函数指针不存在函数的签名信息,甚至可 ...

  7. JAVA8 十大新特性详解

    前言: Java8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.在Java Code Geeks上已经有很多介绍Java 8新特性的文章, 例如Playing with Java ...

  8. 简单理解ECMAScript2015中的箭头函数新特性

    箭头函数(Arrow functions),是ECMAScript2015中新加的特性,它的产生,主要有以下两个原因:一是使得函数表达式(匿名函数)有更简洁的语法,二是它拥有词法作用域的this值,也 ...

  9. paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较

    paip.php 5.0 5.3 5.4  5.5 -6.0的新特性总结与比较 PHP5的新特性 2 · 对象的参照过渡是默认的(default) 3 · 引入访问属性的限制 3 · 引入访问方法的限 ...

随机推荐

  1. C# Unity的使用

    Unity是微软推出的IOC框架, 使用这个框架,可以实现AOP面向切面编程,便于代码的后期维护,此外,这套框架还自带单例模式,可以提高程序的运行效率. 下面是我自己的案例,以供日后参考: 使用VS2 ...

  2. CSS制作渐变背景色

    <style type="text/css"> #grad1 { background: -webkit-linear-gradient(#C2F2F0,#); /* ...

  3. vm中的nat模式不能连接到主机,以及不能上网

    主机能够ping通vm中的ip,但是vm不能ping通主机ip vm不能ping通主机:主要是虚拟机中的gateway的设置和vm的网络编辑器中的网关id不一致造成的 vm不能上外网:dns没有配置正 ...

  4. Linux环境配置文件的理解

    百度百科: .bashrc这个文件主要保存个人的一些个性化设置,如命令别名.路径等.也即在同一个服务器上,只对某个用户的个性化设置相关. 示例: 编辑# User specific aliases a ...

  5. 堆排序 P1090 合并果子

    P1090 合并果子 本题要用到堆 一个小根堆 每次取出两堆,合并成一堆,为了让多多花费体力最少,我们要尽量少的重复大堆的合并,因此每次合并完以后,要把新的一坨放到堆里排一排,维护一个堆 有必要强调一 ...

  6. debugging kubernetes (Delve and Goland)

    1. Build from source cd GOPATH mkdir k8s.io cd k8s.io git clone https://github.com/kubernetes/kubern ...

  7. 关于weblogic部署Java项目的包冲突问题

    我们可能会用各种应用服务部署我们的Java应用,比如Tomcat.WAS.weblogic等.Tomcat和WAS可能会比较少遇到一些奇怪的问题,但是用weblogic部署项目则经常遇到一些比如包冲突 ...

  8. jdbc笔记(一) 使用Statement对单表的CRUD操作

    jdbc连接mysql并执行简单的CRUD的步骤: 1.注册驱动(需要抛出/捕获异常) Class.forName("com.mysql.jdbc.Driver"); 2.建立连接 ...

  9. qt注册表关联文件格式

    注册表相关知识:http://www.360doc.com/content/12/0812/19/3688062_229808059.shtml(超详细超实用) 将某种类型的格式关联到某个可执行程序, ...

  10. 防止sql注入(简单)

    (1)mysql_real_escape_string -- 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集 使用方法如下: $sql = "select count ...