brad-jones / superclosure
使用序列化等方式处理闭包的有趣操作。
Requires
- php: >=5.3.3
- nikic/php-parser: ~1.0
Requires (Dev)
- phpunit/phpunit: ~4.0
This package is not auto-updated.
Last update: 2017-03-22 04:00:35 UTC
README
你见过这个吗?
未捕获异常 'Exception',消息为 '序列化 'Closure' 是不允许的'
这是真的!如果你尝试序列化一个 Closure
,PHP 将抛出异常并告诉你这是不允许的。但是尽管它不被 PHP "允许",Super Closure 库(在 Packagist 上的 jeremeamia/superclosure)让它成为可能。
我不是开玩笑,你真的可以序列化 PHP 闭包!
require 'vendor/autoload.php'; use Jeremeamia\SuperClosure\SerializableClosure; $greeting = 'Hello'; $helloWorld = new SerializableClosure(function ($name = 'World') use ($greeting) { echo "{$greeting}, {$name}!\n"; }); $helloWorld(); //> Hello, World! $helloWorld('Jeremy'); //> Hello, Jeremy! $serialized = serialize($helloWorld); $unserialized = unserialize($serialized); $unserialized(); //> Hello, World! $unserialized('Jeremy'); //> Hello, Jeremy!
是的,很酷吧?
了解更多!
这一切始于2010年初,当时PHP 5.3开始流行起来。我在前雇主的博客HTMList上发表了一篇名为使用序列化和反射扩展PHP 5.3闭包的文章,展示了如何实现。从那时起,我对代码进行了一些迭代,这个最新的迭代带来了一个更稳健的解决方案,它利用了nikic/php-parser库。
功能
- 允许序列化闭包
- 处理使用/继承/导入变量的闭包
- 处理使用其他闭包的闭包
- 处理参数或体中引用类名的闭包
- 处理递归闭包(仅限PHP 5.4+)
- 允许你获取闭包的代码
- 允许你获取闭包使用的变量名和值
- 允许你获取表示闭包代码的抽象语法树(AST)
- 将魔法常量替换为其预期值,以便在反序列化后闭包按预期运行
- 使用nikic/php-parser库通过精确的上下文无关文法解析方法
- PSR-0兼容,可以通过Composer安装
注意事项
- 对于任何使用引用(例如,
function () use (&$vars, &$like, &$these) {…}
)的变量,序列化和反序列化后引用不会保留。唯一的例外是(仅限PHP 5.4+),使用变量是序列化的SerializableClosure
对象的引用,这是递归函数的情况。由于某种原因——我实际上并不完全理解——这行得通。 - 如果你在单行上定义了两个闭包(你本来就不应该这样做),你将无法序列化任何一个,因为不清楚应该解析哪个闭包的代码。
- 由于获取闭包代码和上下文的技术需要反射和完整的AST样式解析,序列化闭包的性能可能不佳。
- 警告:反序列化闭包需要
eval()
和extract()
。许多人都认为这些函数很危险,所以你必须评估是否真的想使用这个库。这些函数必须使用才能使此技术工作。
安装
要使用Composer在项目中安装Super Closure库,首先请将以下内容添加到您的composer.json
配置文件中。
{ "require": { "jeremeamia/superclosure": "~1.0" } }
然后运行Composer的安装或更新命令以完成安装。有关如何使用Composer的更多信息,请访问Composer主页。
为什么我需要序列化闭包?
既然您正在查看这个README文件,您可能已经有了相应的用例。尽管这个概念最初只是一个实验,但在实际应用中已经出现了一些用例。
例如,在UserScape关于Laravel 4和IronMQ的视频中,大约在7:50的位置,他们展示了如何将闭包作为一个工作推送到队列中,以便由工作进程执行。这样做的好处是您不需要为可能非常简单的作业创建整个类。闭包序列化是由基于我较旧版本的SuperClosure的Laravel 4框架中的一个类完成的。
本质上,这个库允许您在一个进程中创建闭包并在另一个进程中使用它们。甚至可以通过API提供闭包(或算法)作为服务。
谁在使用Super Closure?
- Laravel 4 - 序列化闭包以推送到作业队列。
- PHP的HTTP Mock - 序列化闭包以在测试工作流程中发送到远程服务器。
- Jumper - 序列化闭包以通过SSH在远程主机上运行。
- nicmart/Benchmark - 使用
ClosureParser
显示基准测试的闭包代码。 - 请告诉我您的项目是否以及如何使用Super Closure。