Serialize closures

Learn how to serialize closures

This version of the library is no longer maintained. Please consider upgrading to the latest release

Serialize closures

If you ever used closures then you probably know that closures are not serializable. Trying to serialize a closure will result into an exception:

Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed'

The solution for overcoming this problem is to wrap the closure into an Opis\Closure\SerializableClosure object, then serialize the wrapper object using the standard serialize.

use Opis\Closure\SerializableClosure;

// Recursive factorial closure
$factorial = function ($n) use (&$factorial) {
  return $n <= 1 ? 1 : $factorial($n - 1) * $n;
};

// Wrap the closure
$wrapper = new SerializableClosure($factorial);
// Now it can be serialized
$serialized = serialize($wrapper);

Unserialize closures

Closure unserialization is done using the standard unserialize function. Once the wrapper was unserialized, you can directly invoke the wrapper, or you can extract the serialized closure by calling the getClosure method.

// Unserialize the closure
$wrapper = unserialize($serialized);

// You can directly invoke the wrapper...
echo $wrapper(5); //> 120

// Or, the recommended way, extract the closure object
$closure = $wrapper->getClosure();

echo $closure(5); //> 120

Due to the fact that Opis Closure doesn’t use eval in the serialization-deserialization process, all closures can be serialized and unserialized an infinite amount of times.

// Once again, but this time using the previously unserialized closure
$wrapper = new SerializableClosure($closure);
$serialized = serialize($wrapper);
$wrapper = unserialize($serialized);
$closure = $wrapper->getClosure();

// Now watch this...
echo $closure(5); //> 120
// It worked!

The unserializeData method

If you are planning to support PHP 5.3, then you should be aware that there is a bug (fixed in PHP 5.4.0) that will prevent Opis Closure to work properly in certain situations.

This problem can be overcome by using the unserializeData static method of the Opis\Closure\SerializableClosure class, which is just a wrapper for the unserialize function, that will somehow fix the previously mentioned bug.

// Unserialize the closure
$wrapper = SerializableClosure::unserializeData($serialized);

// Extract the closure object
$closure = $wrapper->getClosure();

echo $closure(5); //> 120