Quick start

Learn how to serialize closures

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!

Serialize/unserialize arbitrary objects

Opis Closure allows you to serialize arbitrary objects with the help of the Opis\Closure\serialize function. Unserialization is made by using the Opis\Closure\unserialize function.

use function Opis\Closure\{serialize as s, unserialize as u}

class A
{
    private $closure;
    
    public function __construct()
    {
        $this->closure = function(){
            echo 'It works!';
        };
    }
    
    public function test()
    {
        //call closure
        ($this->closure)();
    }
}

$obj = new A();

u(s($obj))->test(); // It works