PHP 闭包详解及实例代码


Posted in PHP onSeptember 28, 2016

闭包和匿名函数在PHP5.3.0中引入的。

闭包是指:创建时封装周围状态的函数。即使闭包所处的环境不存在了,闭包中封装的状态依然存在。

理论上,闭包和匿名函数是不同的概念。但是PHP将其视作相同概念。

实际上,闭包和匿名函数是伪装成函数的对象。他们是Closure类的实例。

闭包和字符串、整数一样,是一等值类型。

创建闭包

<?php
$clousre = function ($name) {
return 'Hello ' . $name;
};
echo $closure('nesfo');

我们之所以能调用$closure变量,是因为这个变量的值是一个闭包,而且闭包对象实现了__invoke()魔术方法。只要变量名后有(),PHP就会查找并调用__invoke()方法。通常会把PHP闭包当作函数的回调使用。array_map(), preg_replace_callback()方法都会用到回调函数,这是使用闭包的最佳时机!

举个例子:

<?php
$numbersPlusOne = array_map(function ($number) {
return $number + 1;
}, [1, 2, 3]);
print_r($numbersPlusOne);

得到结果:

[2, 3, 4]

在闭包出现之前,只能单独创建具名函数,然后使用名称引用那个函数。这么做,代码执行会稍微慢点,而且把回调的实现和使用场景隔离了。

<?php
function incrementNum ($number) {
return $number + 1;
}
$numbersPlusOne = array_map('incrementNum', [1, 2, 3]);
print_r($numbersPlusOne);

附加状态

匿名函数不止可以当回调使用,还可以为PHP附加并封装状态。

PHP中,必须手动调用闭包对象的bindTo()方法或者使用use关键字,才能把状态附加到PHP闭包上。

<?php
function enclosePerson ($name) {
return function ($doCommand) use ($name) {
return $name . ', ' . $doCommand;
}
}
$clay = enclosePerson('Clay');
echo $clay('get me sweet tea!');

得到结果:

"Clay, get me sweet tea!"

PHP闭包是对象,每个闭包实例都可以使用$this关键字获取闭包的内部状态。闭包对象的默认状态没什么用,只有__invoke()方法和bindTo方法而已。

我们可以使用bindTo()这个方法,将Closure对象的内部状态绑定到其它对象上。

bindTo()方法的第二个参数:其作用是指定绑定闭包的那个对象所属的PHP类。因此,闭包可以访问绑定闭包的对象中受保护和私有的成员。

PHP框架经常使用bindTo()方法把路由URL映射到匿名回调函数上。这么做可以在这个匿名函数中使用$this关键字引用重要的应用对象。

使用bindTo()方法附加闭包状态

<?php
class App
{
protected $routes = [];
protected $responseStatus = '200 OK';
protected $responseContentType = 'text/html';
protected $responseBody = 'Hello world';
public function addRoute($routePath, $routeCallback){
$this->routes[$routePath] = $routeCallback->bindTo($this, __CLASS__);
}
public function dispatch($currentPath){
foreach($this->routes as $routePath => $callback){
if ($routePath === $currentPath) {
$callback();
}
}
header('HTTP/1.1' . $this->responseStatus);
header('Content-type: ' . $this->responseContentType);
header('Content-length' . mb_strlen($this->responseBody));
echo $this->responseBody;
}
}
<?php
$app = new App();
$app->addRoute('/user/nesfo', function () {
$this->responseContentType = 'application/json; charset=utf8';
$this->responseBody = '{"name": "nesfo"}';
});
$app->dispatch('/user/nesfo');

以上就是对PHP 闭包资料的资料整理,后续继续补充相关资料谢谢大家对本站的支持!

PHP 相关文章推荐
IIS+PHP+MySQL+Zend配置 (视频教程)
Dec 13 PHP
php设置session值和cookies的学习示例
Mar 21 PHP
PHP面向对象之后期静态绑定功能介绍
May 18 PHP
php准确获取文件MIME类型的方法
Jun 17 PHP
SSO单点登录的PHP实现方法(Laravel框架)
Mar 23 PHP
PHP 表单提交及处理表单数据详解及实例
Dec 27 PHP
PHP正则匹配反斜杠'\'和美元'$'的方法
Feb 08 PHP
PHP重定向与伪静态区别
Feb 19 PHP
Ajax+PHP实现的删除数据功能示例
Feb 12 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
Mar 14 PHP
PHP架构及原理知识点详解
Dec 22 PHP
PHP使用PDO实现mysql防注入功能详解
Dec 20 PHP
php类的自动加载操作实例详解
Sep 28 #PHP
PHP对象克隆clone用法示例
Sep 28 #PHP
PHP简单遍历对象示例
Sep 28 #PHP
PHP标准类(stdclass)用法示例
Sep 28 #PHP
PHP类型约束用法示例
Sep 28 #PHP
PHP类和对象相关系统函数与运算符小结
Sep 28 #PHP
PHP序列化操作方法分析
Sep 28 #PHP
You might like
php发送与接收流文件的方法
2015/02/11 PHP
PHP的Yii框架中过滤器相关的使用总结
2016/03/29 PHP
用php+ajax新建流程(请假、进货、出货等)
2017/06/11 PHP
javascript面向对象包装类Class封装类库剖析
2013/01/24 Javascript
jquery任意位置浮动固定层插件用法实例
2015/05/29 Javascript
仅9张思维导图帮你轻松学习Javascript 就这么简单
2016/06/01 Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
2019/01/17 Javascript
layer.msg()去掉默认时间,实现手动关闭的方法
2019/09/12 Javascript
详解一些适用于Node.js的命名约定
2019/12/08 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
如何解决jQuery 和其他JS库的冲突
2020/06/22 jQuery
vue项目使用$router.go(-1)返回时刷新原来的界面操作
2020/07/26 Javascript
在react-antd中弹出层form内容传递给父组件的操作
2020/10/24 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
python BeautifulSoup使用方法详解
2013/11/21 Python
初学Python实用技巧两则
2014/08/29 Python
在Python的循环体中使用else语句的方法
2015/03/30 Python
python使用post提交数据到远程url的方法
2015/04/29 Python
详细讲解Python中的文件I/O操作
2015/05/24 Python
Python文档生成工具pydoc使用介绍
2015/06/02 Python
Python开发中爬虫使用代理proxy抓取网页的方法示例
2017/09/26 Python
python Celery定时任务的示例
2018/03/13 Python
基于循环神经网络(RNN)的古诗生成器
2018/03/26 Python
Python画图实现同一结点多个柱状图的示例
2019/07/07 Python
python 爬取学信网登录页面的例子
2019/08/13 Python
jupyter note 实现将数据保存为word
2020/04/14 Python
Python使用pdb调试代码的技巧
2020/05/03 Python
使用python-cv2实现Harr+Adaboost人脸识别的示例
2020/10/27 Python
Pycharm同步远程服务器调试的方法步骤
2020/11/04 Python
Python爬虫逆向分析某云音乐加密参数的实例分析
2020/12/04 Python
CSS3点击按钮实现背景渐变动画效果
2016/10/19 HTML / CSS
Marlies Dekkers内衣法国官方网上商店:国际知名的荷兰内衣品牌
2019/03/18 全球购物
校园文化建设方案
2014/02/03 职场文书
公民授权委托书范本
2014/09/17 职场文书
企业党员岗位承诺书
2015/04/27 职场文书
学前班教学反思
2016/02/24 职场文书