PHPackages                             jeremeamia/superclosure - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. jeremeamia/superclosure

Abandoned → [opis/closure](/?search=opis%2Fclosure)Library[Parsing &amp; Serialization](/categories/parsing)

jeremeamia/superclosure
=======================

Serialize Closure objects, including their context and binding

2.4.0(8y ago)1.7k60.5M—1.1%94[1 PRs](https://github.com/jeremeamia/super_closure/pulls)20MITPHPPHP &gt;=5.4

Since Apr 14Pushed 2y ago31 watchersCompare

[ Source](https://github.com/jeremeamia/super_closure)[ Packagist](https://packagist.org/packages/jeremeamia/superclosure)[ Docs](https://github.com/jeremeamia/super_closure)[ RSS](/packages/jeremeamia-superclosure/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (22)Used By (20)

PHP SuperClosure
================

[](#php-superclosure)

[![Total Downloads](https://camo.githubusercontent.com/7daede889de2b8a865e6d1582ffbc38e3882ee03c482b55bea2c2e2f02b0df49/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a6572656d65616d69612f7375706572636c6f737572652e7376673f7374796c653d666c6174)](https://packagist.org/packages/jeremeamia/superclosure)[![Build Status](https://camo.githubusercontent.com/3502a0ec07de3039d8a422f8f85191c097637d5469a057a2048fc6677f36a339/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6a6572656d65616d69612f73757065725f636c6f737572652f6d61737465722e7376673f7374796c653d666c6174)](https://travis-ci.org/jeremeamia/super_closure)[![MIT License](https://camo.githubusercontent.com/9ca994e311e830e0eb3c579f87574779ba054ee68d1c61677ca4f9bc96cb171c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6a6572656d65616d69612f7375706572636c6f737572652e7376673f7374796c653d666c6174)](https://github.com/jeremeamia/super_closure/blob/master/LICENSE.md)[![Gitter](https://camo.githubusercontent.com/abe08b740a4156153736f791393ec4da6619c4be73212e75769f52edacc0e2b5/68747470733a2f2f6261646765732e6769747465722e696d2f4a6f696e253230436861742e737667)](https://gitter.im/jeremeamia/super_closure)

A PHP Library for serializing closures and anonymous functions.

---

No Longer Maintained
--------------------

[](#no-longer-maintained)

This software is no longer maintained. Consider using [opis/closure](https://github.com/opis/closure) instead.

The rest of the README will remain intact as it was prior to the software being abandoned.

---

Introduction
------------

[](#introduction)

Once upon a time, I tried to serialize a PHP `Closure` object. As you can probably guess, it doesn't work at all. In fact, you get a very specific error message from the PHP Runtime:

> Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed'

Even though serializing closures is "not allowed" by PHP, the SuperClosure library makes it **possible**. Here's the way you use it:

```
use SuperClosure\Serializer;

$serializer = new Serializer();

$greeting = 'Hello';
$hello = function ($name = 'World') use ($greeting) {
    echo "{$greeting}, {$name}!\n";
};

$hello('Jeremy');
//> Hello, Jeremy!

$serialized = $serializer->serialize($hello);
// ...
$unserialized = $serializer->unserialize($serialized);

$unserialized('Jeremy');
//> Hello, Jeremy!
```

Yep, pretty cool, right?

### Features

[](#features)

SuperClosure comes with two different **Closure Analyzers**, which each support different features regarding the serialization of closures. The `TokenAnalyzer`is not as robust as the `AstAnalyzer`, but it is around 20-25 times faster. Using the table below, and keeping in mind what your closure's code looks like, you should *choose the fastest analyzer that supports the features you need*.

   Supported Features Via `AstAnalyzer` Via `TokenAnalyzer`      Regular closures (anonymous functions)
 `$fn = function (...) {...};`  Yes Yes    Closures with context
 `$fn = function () use ($a, $b, ...) {...};`  Yes Yes    Recursive closures
 `$fn = function () use (&$fn, ...) {...};`  Yes Yes    Closures bound to an object
 `$fn = function () {$this->something(); ...};`  Yes Yes    Closures scoped to an object
 `$fn = function () {self::something(); ...};`  Yes Yes    Static closures (i.e, preserves the `static`-ness)
 `$fn = static function () {...};`  Yes --    Closures with class name in params
 `$fn = function (Foo $foo) {...};`  Yes --    Closures with class name in body
 `$fn = function () {$foo = new Foo; ...};`  Yes --    Closures with magic constants
 `$fn = function () {$file = __FILE__; ...};`  Yes --   Performance *Slow* *Fast*  ### Caveats

[](#caveats)

1. For any variables used by reference (e.g., `function () use (&$vars, &$like,   &$these) {…}`), the references are not maintained after serialization. The only exception to this is recursive closure references.
2. If you have two closures defined on a single line (why would you do this anyway?), you will not be able to serialize either one since it is ambiguous which closure's code should be parsed (they are *anonymous* functions after all).
3. **Warning**: The `eval()` function is required to unserialize the closure. This function is considered dangerous by many, so you will have to evaluate what precautions you may need to take when using this library. You should only unserialize closures retrieved from a trusted source, otherwise you are opening yourself up to code injection attacks. It is a good idea sign serialized closures if you plan on storing or transporting them. Read the **Signing Closures** section below for details on how to do this.
4. Cannot serialize closures that are defined within `eval()`'d code. This includes re-serializing a closure that has been unserialized.

### Analyzers

[](#analyzers)

You can choose the analyzer you want to use when you instantiate the `Serializer`. If you do not specify one, the `AstAnalyzer` is used by default, since it has the most capabilities.

```
use SuperClosure\Serializer;
use SuperClosure\Analyzer\AstAnalyzer;
use SuperClosure\Analyzer\TokenAnalyzer;

// Use the default analyzer.
$serializer = new Serializer();

// Explicitly choose an analyzer.
$serializer = new Serializer(new AstAnalyzer());
// OR
$serializer = new Serializer(new TokenAnalyzer());
```

Analyzers are also useful on their own if you are just looking to do some introspection on a Closure object. Check out what is returned when using the `AstAnalyzer`:

```
use SuperClosure\Analyzer\AstAnalyzer;

class Calculator
{
    public function getAdder($operand)
    {
        return function ($number) use ($operand) {
            return $number + $operand;
        };
    }
}

$closure = (new Calculator)->getAdder(5);
$analyzer = new AstAnalyzer();

var_dump($analyzer->analyze($closure));
// array(10) {
//   'reflection' => class ReflectionFunction#5 (1) {...}
//   'code' => string(68) "function ($number) use($operand) {
//     return $number + $operand;
// };"
//   'hasThis' => bool(false)
//   'context' => array(1) {
//     'operand' => int(5)
//   }
//   'hasRefs' => bool(false)
//   'binding' => class Calculator#2 (0) {...}
//   'scope' => string(10) "Calculator"
//   'isStatic' => bool(false)
//   'ast' => class PhpParser\Node\Expr\Closure#13 (2) {...}
//   'location' => array(8) {
//     'class' => string(11) "\Calculator"
//     'directory' => string(47) "/Users/lindblom/Projects/{...}/SuperClosureTest"
//     'file' => string(58) "/Users/lindblom/Projects/{...}/SuperClosureTest/simple.php"
//     'function' => string(9) "{closure}"
//     'line' => int(11)
//     'method' => string(22) "\Calculator::{closure}"
//     'namespace' => NULL
//     'trait' => NULL
//   }
// }
```

### Signing Closures

[](#signing-closures)

Version 2.1+ of SuperClosure allows you to specify a signing key, when you instantiate the Serializer. Doing this will configure your Serializer to sign any closures you serialize and verify the signatures of any closures you unserialize. Doing this can help protect you from code injection attacks that could potentially happen if someone tampered with a serialized closure. *Remember to keep your signing key secret*.

```
$serializer1 = new SuperClosure\Serializer(null, $yourSecretSigningKey);
$data = $serializer1->serialize(function () {echo "Hello!\n";});
echo $data . "\n";
// %rv9zNtTArySx/1803fgk3rPS1RO4uOPPaoZfTRWp554=C:32:"SuperClosure\Serializa...

$serializer2 = new SuperClosure\Serializer(null, $incorrectKey);
try {
    $fn = $serializer2->unserialize($data);
} catch (SuperClosure\Exception\ClosureUnserializationException $e) {
    echo $e->getMessage() . "\n";
}
// The signature of the closure's data is invalid, which means the serialized
// closure has been modified and is unsafe to unserialize.
```

Installation
------------

[](#installation)

To install the Super Closure library in your project using Composer, simply require the project with Composer:

```
$ composer require jeremeamia/superclosure
```

You may of course manually update your require block if you so choose:

```
{
    "require": {
        "jeremeamia/superclosure": "^2.0"
    }
}
```

Please visit the [Composer homepage](http://getcomposer.org) for more information about how to use Composer.

Why would I need to serialize a closure?
----------------------------------------

[](#why-would-i-need-to-serialize-a-closure)

Well, since you are here looking at this README, you may already have a use case in mind. Even though this concept began as an experiment, there have been some use cases that have come up in the wild.

For example, in a [video about Laravel and IronMQ](http://vimeo.com/64703617) by [UserScape](http://www.userscape.com), at about the 7:50 mark they show how you can push a closure onto a queue as a job so that it can be executed by a worker. This is nice because you do not have to create a whole class for a job that might be really simple.

Or... you might have a dependency injection container or router object that is built by writing closures. If you wanted to cache that, you would need to be able to serialize it.

In general, however, serializing closures should probably be avoided.

Tell me about how this project started
--------------------------------------

[](#tell-me-about-how-this-project-started)

It all started back in the beginning of 2010 when PHP 5.3 was starting to gain traction. I set out to prove that serializing a closure could be done, despite that PHP wouldn't let me do it. I wrote a blog post called [Extending PHP 5.3 Closures with Serialization and Reflection](http://www.htmlist.com/development/extending-php-5-3-closures-with-serialization-and-reflection/) on my former employers' blog, [HTMList](http://www.htmlist.com), showing how it could be done. I also released the code on GitHub.

Since then, I've made a few iterations on the code, and the most recent iterations have been more robust, thanks to the usage of the fabulous [nikic/php-parser](https://github.com/nikic/PHP-Parser) library.

Who is using SuperClosure?
--------------------------

[](#who-is-using-superclosure)

- [Laravel](https://github.com/laravel/framework) - Serializes a closure to potentially push onto a job queue.
- [HTTP Mock for PHP](https://github.com/InterNations/http-mock) - Serialize a closure to send to remote server within a test workflow.
- [Jumper](https://github.com/kakawait/Jumper) - Serialize a closure to run on remote host via SSH.
- [nicmart/Benchmark](https://github.com/nicmart/Benchmark) - Uses the `ClosureParser` to display a benchmarked Closure's code.
- [florianv/business](https://github.com/florianv/business) - Serializes special days to store business days definitions.
- [zumba/json-serializer](https://github.com/zumba/json-serializer) - Serializes PHP variables into JSON format.
- [PHP-DI](http://php-di.org/) - Compiles closure definitions into optimized PHP code.
- Please let me know if and how your project uses Super Closure.

Alternatives
------------

[](#alternatives)

This year the [Opis Closure](https://github.com/opis/closure) library has been introduced, that also provides the ability to serialize a closure. You should check it out as well and see which one suits your needs the best.

If you wish to export your closures as executable PHP code instead, you can check out the [brick/varexporter](https://github.com/brick/varexporter) library.

###  Health Score

54

—

FairBetter than 97% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity74

Solid adoption and visibility

Community47

Growing community involvement

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 55.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~108 days

Recently: every ~209 days

Total

21

Last Release

2980d ago

Major Versions

0.9.2 → 1.0.02013-06-14

0.8.x-dev → 1.0.12013-10-09

1.0.1 → 2.0-alpha12014-01-14

1.0.2 → 2.0.0-beta.12015-01-19

PHP version history (3 changes)0.9.0PHP &gt;=5.3.2

0.9.1PHP &gt;=5.3.3

2.0.0-beta.1PHP &gt;=5.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/184fbc398ff1b83855ab8289cd8ce20225d0158c66284b458d2d811546606938?d=identicon)[jeremeamia](/maintainers/jeremeamia)

---

Top Contributors

[![jeremeamia](https://avatars.githubusercontent.com/u/107867?v=4)](https://github.com/jeremeamia "jeremeamia (95 commits)")[![GrahamCampbell](https://avatars.githubusercontent.com/u/2829600?v=4)](https://github.com/GrahamCampbell "GrahamCampbell (62 commits)")[![nikic](https://avatars.githubusercontent.com/u/216080?v=4)](https://github.com/nikic "nikic (2 commits)")[![lstrojny](https://avatars.githubusercontent.com/u/79707?v=4)](https://github.com/lstrojny "lstrojny (2 commits)")[![florianv](https://avatars.githubusercontent.com/u/1586668?v=4)](https://github.com/florianv "florianv (1 commits)")[![jrbasso](https://avatars.githubusercontent.com/u/26548?v=4)](https://github.com/jrbasso "jrbasso (1 commits)")[![mnapoli](https://avatars.githubusercontent.com/u/720328?v=4)](https://github.com/mnapoli "mnapoli (1 commits)")[![ntzm](https://avatars.githubusercontent.com/u/3888578?v=4)](https://github.com/ntzm "ntzm (1 commits)")[![remicollet](https://avatars.githubusercontent.com/u/270445?v=4)](https://github.com/remicollet "remicollet (1 commits)")[![asgrim](https://avatars.githubusercontent.com/u/496145?v=4)](https://github.com/asgrim "asgrim (1 commits)")[![Remo](https://avatars.githubusercontent.com/u/129864?v=4)](https://github.com/Remo "Remo (1 commits)")[![BenMorel](https://avatars.githubusercontent.com/u/1952838?v=4)](https://github.com/BenMorel "BenMorel (1 commits)")[![dortort](https://avatars.githubusercontent.com/u/1169721?v=4)](https://github.com/dortort "dortort (1 commits)")[![drbyte](https://avatars.githubusercontent.com/u/404472?v=4)](https://github.com/drbyte "drbyte (1 commits)")

---

Tags

parserserializeserializableclosurefunctiontokenizerlambda

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/jeremeamia-superclosure/health.svg)

```
[![Health](https://phpackages.com/badges/jeremeamia-superclosure/health.svg)](https://phpackages.com/packages/jeremeamia-superclosure)
```

###  Alternatives

[opis/closure

A library that can be used to serialize closures (anonymous functions) and arbitrary data.

2.6k230.0M284](/packages/opis-closure)[jeremeamia/functionparser

Function parser for PHP functions, methods, and closures

48169.7k6](/packages/jeremeamia-functionparser)[nicoswd/php-rule-parser

Rule Engine - Rule Parser &amp; Evaluator

13078.6k7](/packages/nicoswd-php-rule-parser)[composer-unused/symbol-parser

Toolkit to parse symbols from a composer package

145.7M2](/packages/composer-unused-symbol-parser)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
