博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP闭包和匿名函数
阅读量:5226 次
发布时间:2019-06-14

本文共 2345 字,大约阅读时间需要 7 分钟。

概念

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

闭包

  闭包是指创建时封装周围环境的函数。即使闭包所在的环境不存在了,闭包中封装的状态依然存在。这个概念很难理解,不过没关系,继续看下去就会明白了。

匿名函数

  匿名函数就是没有名字的函数。匿名函数可以赋值给变量,还能像其他任何PHP对象那样传递。不过匿名函数仍然是函数,因此可以调用可以传递参数。匿名函数特别适合作为函数或者方法的回调

  注意:理论上来说,闭包和匿名函数是不同的概念。不过,PHP将其视作相同的概念。

  PHP闭包和匿名函数使用的句法和普通函数相同,但是要注意,闭包和匿名函数其实是伪装成函数的对象,如果你审查PHP闭包或匿名函数,就会发现它们是 Closure类的实例。

创建闭包

举个?

如上,我们创建了一个简单的闭包对象,然后将它赋值给了$closure变量。

 

我们之所以能调用$closure变量,是因为这个变量的值是一个闭包,并且闭包对象实现了__invoke()魔术方法。只要变量名后有(),PHP就会查找并调用__invoke()方法。

常用地方

我通常PHP闭包当做函数和方法的回调使用。PHP很多函数都会用到回调函数,如arrar_map()preg_replace_callback()。记住,闭包和其他值一样,可以作为参数传入其他PHP函数

举个?

2 [1] => 3 [2] => 4 )

附加状态

  前面说的都是基础,重点来了。

  前面我演示了如何把匿名函数当做回调使用,下面探讨如何为PHP闭包附加状态并封装状态。JavaScript开发者可能会对PHP闭包感觉奇怪,因为PHP闭包不会像真正的JavaScript闭包那样自动封装应用的状态。在PHP中必须手动调用闭包对象的bindTo()方法或者使用use关键字,把状态附加到PHP闭包上。

use 关键字

使用use关键字附加闭包状态很常见,因此先看这种方式。

举个?,使用 use 关键字附加闭包状态

具名函数 enclosePerson() 有个名为 $name的参数,这个函数返回一个闭包对象,而且这个对象中封装了$name参数。即使返回的闭包对象跳出了 enclosePerson()函数的作用域,它也会记住$name的值,因为$name变量仍在闭包中。

注意:使用 use 关键字可以把多个参数传入闭包,此时要像PHP函数或方法的参数一样,使用逗号分隔多个参数。

bindTo()

  别忘了,PHP闭包是对象,与其他PHP对象类似,每个闭包实例都可以使用$this关键字获取闭包的内部状态。闭包的默认方法没什么用,不过有一个__invoke()魔术方法和bindTo()方法,仅此而已。

  但是,bindTo()方法为闭包增加了一些有趣的潜力。我们可以使用这个方法把Closure对象的内部状态绑定到其他对象上。bindTo()方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的PHP类。因此,闭包可以访问绑定闭包的对象中受保护和私有的成员变量。

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

举个?,使用bindTo()方法附加闭包的状态

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; }}

  我们要特别注意addRoute()方法。这个方法的参数分别是一个路由路径(如/users/martini)和一个路由回调。dispatch()方法的参数是当前HTTP请求的路径,它会调用匹配的路由回调。addRoute()方法是重点所在,我们把路由回调绑定到了当前的App实例上,这样做能在回调函数中处理App实例的状态:

addRoute('/users/martini', function() { $this->responseContentType = 'application/json;charset-utf8'; $this->responseBody = '{"name": "martini"}';});$app->dispatch('/users/martini'); // 输出 {"name": "martini"}

 

转载于:https://www.cnblogs.com/martini-d/p/10910003.html

你可能感兴趣的文章
API抓屏
查看>>
c#进阶(7)—— 异步编程基础(async 和 await 关键字)
查看>>
系统设计与分析(三)
查看>>
Spark MLlib 保序回归
查看>>
001.libev安装及eclipse下添加libev库链接
查看>>
【洛谷p1258】小车问题
查看>>
1021.Deepest Root (并查集+DFS树的深度)
查看>>
eMMC基础技术9:分区管理
查看>>
图的储存方式4.28
查看>>
centos 7 上测试网速
查看>>
Delphi AnimateWindow 用法 淡入淡出窗口
查看>>
本地通知
查看>>
页面视图中的按钮操作指向
查看>>
mongoose中给字段添加索引的方法
查看>>
mysqlsh : mysql shell tutorial
查看>>
paas容器云
查看>>
史上最全的第三方 (一)
查看>>
学习笔记39_EF的DAL层(精)
查看>>
tomcat配置
查看>>
linux命令
查看>>