Luminova Framework

PHP Luminova: Anonymous Functions and Closure Serializer

Last updated: 2026-03-04 00:08:27

Luminova Closure Serializer allows you to convert anonymous functions into a storable string format, so you can save them and restore them later when needed.

The Luminova Closure Serializer allows you to convert anonymous functions (closures) into a storable string format and restore them later into executable functions.

PHP does not natively support serializing closures. Once your application ends, any anonymous function is gone. Luminova solves this by extracting the closure’s source code, captured variables, scope information, and signature, then rebuilding it when needed.

This makes it possible to:

  • Store closures in a database
  • Cache dynamic logic
  • Queue and background-task executable callbacks
  • Share runtime-defined logic between processes
  • Rehydrate previously defined closures in CLI or web contexts

In short, you can define logic now and execute it later, even across requests.

The serializer signs every serialized closure using sha256 combined with your application key. This ensures the payload has not been tampered with before it is restored.


Important Note

Luminova Closure Serializer is designed for practical, lightweight closure serialization. It signs serialized closures using sha256 together with your application key to ensure integrity.

Internally, it evaluates restored closures using eval, and it does not currently provide advanced handling for dynamically updated global variable references.

For straightforward use cases where performance and simplicity are the priority, Luminova’s implementation is efficient and sufficient.

For more complex scenarios, especially where advanced security requirements or deeper global reference handling are critical. Using Opis Closure is recommended, as it offers extended capabilities and avoids relying on eval during restoration.


Examples

Below are practical examples showing how the Luminova closure serializer converts anonymous functions into a storable string and restores them back into working closures.


Serialize a Simple Closure

Convert any anonymous function into a string that can be stored in a database, cache, or file.

use Luminova\Utility\Serializer;

$fn = function(string $name): string {
    return "Hello, {$name}!";
};

$serialized = Serializer::serialize($fn);

echo $serialized; 
// Returns a string representation of the closure.

Unserialize and Execute

Restore a previously serialized closure and execute it like a normal function.

use Luminova\Utility\Serializer;

$fn = fn(string $name): string => "Hello, {$name}!";

$serialized = Serializer::serialize($fn);

$closure = Serializer::unserialize($serialized);

echo $closure('World'); 
// Hello, World!

Key point:The restored closure behaves exactly like the original. Parameters and return types are preserved.


Closures Updating Variables by Reference

This example shows how closures can update external variables by reference. When a closure captures a variable by reference (&$var), changes inside the closure persist outside.

use Luminova\Utility\Serializer;

$counter = 0;
$obj = new \stdClass();
$obj->value = 10;

// Capture $counter by reference and $obj by value (object behaves like reference)
$fn = function () use (&$counter, $obj) {
    $counter++;
    $obj->value++;
    return [$counter, $obj->value];
};

$packed = Serializer::serialize($fn);

$restored = Serializer::unserialize($packed);

var_export($restored());
// array (0 => 1,1 => 11)

var_export($restored());
// array (0 => 2,1 => 12)

var_export($restored());
// array (0 => 3,1 => 13)

Serialize and Restore Recursive Closure

To serialize a recursive closure. The serializing and then unserializing, closures can be stored or passed around and later executed with its recursion.

use Luminova\Utility\Serializer;

$fn = function (int $n) use (&$fn) {
    return $n <= 1 ? 1 : $n * $fn($n - 1);
};

$packed = Serializer::serialize($fn);
$restored = Serializer::unserialize($packed);

// Call the restored closure
echo $restored(5); // Outputs: 120

Closures with use Variables

Closures often depend on external variables. These values are captured and restored correctly.

use Luminova\Utility\Serializer;

$testUse = 'TestVar';

$fn = function(string $ctx) use ($testUse): string {
    return "Hello {$ctx}, {$testUse}";
};

$packed = Serializer::serialize($fn);
$restored = Serializer::unserialize($packed);

echo $restored('Closure'); 
// Hello Closure, TestVar

Note:

The $testUse variable is stored as part of the closure’s context, so the restored version still has access to it.


Capturing Objects

Closures that capture objects are also supported.

use Luminova\Utility\Serializer;

$obj = new stdClass();
$obj->name = 'ObjectName';

$fn = function() use ($obj) {
    return "Name: {$obj->name}";
};

$packed = Serializer::serialize($fn);
$restored = Serializer::unserialize($packed);

echo $restored(); 
// Name: ObjectName

Note:The object state at the time of serialization is preserved.


Binding to $this Scope

Closures created inside objects keep their bound scope.

use Luminova\Utility\Serializer;
use Closure;

$obj = new class {
    public string $prefix = 'Scope';

    public function getClosure(): Closure {
        return function(string $ctx) {
            return "{$this->prefix}: {$ctx}";
        };
    }
};

$fn = $obj->getClosure();

$packed = Serializer::serialize($fn);
$restored = Serializer::unserialize($packed);

echo $restored('Hello'); 
// Scope: Hello

Important:

The closure remains bound to its original object context after restoration.


Nested Closures

Closures defined inside other closures are handled correctly.

use Luminova\Utility\Serializer;

$fn = function(string $ctx) {
    $inner = function(string $name) use ($ctx) {
        return "{$ctx} -> {$name}";
    };

    return $inner('Nested');
};

$packed = Serializer::serialize($fn);
$restored = Serializer::unserialize($packed);

echo $restored('Outer'); 
// Outer -> Nested

Multiple Captured Variables

Closures can capture multiple scalar and array variables.

use Luminova\Utility\Serializer;

$a = 1;
$b = 2;
$c = [3, 4];

$fn = function() use ($a, $b, $c) {
    return $a + $b + array_sum($c);
};

$packed = Serializer::serialize($fn);
$restored = Serializer::unserialize($packed);

echo $restored(); 
// 10

Class Definition

  • Full namespace: \Luminova\Utility\Serializer
  • This class is a Final class

Methods

serialize

Serialize a closure to string.

This method converts a Closure into a string representation that captures its code,scope, and any variables it uses. It handles both regular and arrow functions, andsupports closures that capture variables from their surrounding scope.

public static serialize(\Closure $closure, bool $sign = false): string

Parameters:

ParameterTypeDescription
$closure\ClosureThe closure to serialize.
$signboolWhether to sign and include a security signature for the serialized closure.

Return Value:

string - Returns the serialized string representation of the closure.

Throws:


unserialize

Unserialize a closure from string.

This method takes a serialized string representation of a closure (produced by the serialize method)and reconstructs the original Closure object.

It evaluates the closure code in the correct scope and binds it to the appropriate object if necessary.

public static unserialize(string $serialized, array<string,mixed> $options = []): ?Closure

Parameters:

ParameterTypeDescription
$serializedstringThe serialized string representation of the closure.
$optionsarray<string,mixed>Optional unserialize options or application key for verifying signature:
key - Optional sign key of the serialized closure verification.
allowed_classes - Weather to allow class (default: true).

Return Value:

\Closure|null - Returns the unserialized Closure object, or null if the input is invalid or cannot be unserialized.

Throws:


isClosure

Check if a serialized string is a closure.

This method checks if the given serialized string is a valid closure representation producedby the serialize method.

public static isClosure(string $serialized): bool

Parameters:

ParameterTypeDescription
$serializedstringThe serialized string to check.

Return Value:

bool - Returns true if the string is a valid serialized closure, false otherwise.


isValid

Verify if serialized closure signature is valid.

This method checks if the given serialized string is a valid closure representation producedby the serialize method and verifies signature if is signed.

public static isValid(string $serialized, array<string,mixed> $options = []): bool

Parameters:

ParameterTypeDescription
$serializedstringThe serialized closure string.
$optionsarray<string,mixed>Optional unserialize options or application key for verifying signature:
key - Optional sign key of the serialized closure verification.
allowed_classes - Weather to allow class (default: true).

Return Value:

bool - Return true if is valid closure, otherwise false.

Throws: