Serialize closures. Not maintained. Consider using opis/closure.

Overview

PHP SuperClosure

Total Downloads Build Status MIT License Gitter

A PHP Library for serializing closures and anonymous functions.


No Longer Maintained

This software is no longer maintained. Consider using opis/closure instead.

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


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

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

  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

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

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

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 for more information about how to use Composer.

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 by UserScape, 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

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 on my former employers' blog, HTMList, 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 library.

Who is using SuperClosure?

  • Laravel - Serializes a closure to potentially push onto a job queue.
  • HTTP Mock for PHP - Serialize a closure to send to remote server within a test workflow.
  • Jumper - Serialize a closure to run on remote host via SSH.
  • nicmart/Benchmark - Uses the ClosureParser to display a benchmarked Closure's code.
  • florianv/business - Serializes special days to store business days definitions.
  • zumba/json-serializer - Serializes PHP variables into JSON format.
  • PHP-DI - Compiles closure definitions into optimized PHP code.
  • Please let me know if and how your project uses Super Closure.

Alternatives

This year the 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 library.

Comments
  • Magic invocation breaks pass by-ref

    Magic invocation breaks pass by-ref

    When invoking the closure through the __invoke magic method, values which should be passed by-ref are, instead, passed by-value.

    Test code:

      use Jeremeamia\SuperClosure\SerializableClosure;
    
      $closure = function(&$ref = null) {
        $ref = "new value!";
      };
    
      $sclosure = new SerializableClosure($closure);
    
    
      $var1 = null;
      $closure($var1);
    
      $var2 = null;
      $sclosure($var2);
    
      var_dump($var1, $var2);
    

    Outputs:

    string 'new value!' (length=10)
    null
    

    Expected:

    string 'new value!' (length=10)
    string 'new value!' (length=10)
    

    Now, I'm not so sure about previous versions, but a patch I've applied to SerializableClosure.php that works for 5.4 is as follows:

        public function __invoke(&$arg0 = null, &$arg1 = null, &$arg2 = null, &$arg3 = null, &$arg4 = null, &$arg5 = null, &$arg6 = null, &$arg7 = null, &$arg8 = null, &$arg9 = null)
        {
          $stack = debug_backtrace(0);
          return $this->getReflection()->invokeArgs($stack[0]['args']);
        }
    

    Granted, this is pretty hacky (and limits the caller to "only" 10 by-ref arguments), but it gets the job done in about the only way I could figure out.

    I didn't put it through as much testing as I probably should have, but what I did test is that: a) It allows for references to be passed through properly (outside the known limitation of by-ref parameters needing to be explicitly listed). b) By-val parameters are not actually passed by-ref if the closure itself does not expect them to be. c) Actual parameter counts/requirements aren't impacted.

    With the patch in place, the test code above outputs what we'd expect:

    string 'new value!' (length=10)
    string 'new value!' (length=10)
    
    Discussion Won't Fix 
    opened by Ceiu 15
  • Release 2.2.0

    Release 2.2.0

    I think we're ready to release 2,2,0 now @jeremeamia. There are two things potentially stopping us though:

    1. https://github.com/jeremeamia/super_closure/pull/53 might need reviewing first.
    2. You might want to wait for the final PHP 7.0.0 release before we say that 2.2.0 is 100% PHP 7 compatible.
    opened by GrahamCampbell 12
  • [Proposal] Add bindTo support

    [Proposal] Add bindTo support

    Hey friend!

    I'm trying to change the binding of the decorated Closure, with much difficulty. It's private, so a subclass of SerializableClosure wont work. Would you be open to be adding bindTo support?

    opened by assertchris 12
  • SuperClosure v2.0-alpha1 Feedback

    SuperClosure v2.0-alpha1 Feedback

    I recently tagged v2.0-alpha1. Please read the release notes, check out the code, and let me know what you think. I'd love some feedback, suggestions, ideas, etc. Thanks.

    Discussion 
    opened by jeremeamia 12
  • Cannot instantiate interface PhpParser\Parser

    Cannot instantiate interface PhpParser\Parser

    Hello Jeremeamia, I notice an issue with version 2.2.0 of your project. The function below wouldn't work

    private function getFileAst(\ReflectionFunction $reflection)
        {
            $fileName = $reflection->getFileName();
            if (!file_exists($fileName)) {
                throw new ClosureAnalysisException(
                    "The file containing the closure, \"{$fileName}\" did not exist."
                );
            }
    
    
            return $this->getParser()->parse(file_get_contents($fileName)); // This line doesn't work
        }
    

    With version v2.1.0 of nikic/php-parser, Parser is no longer a class but an interface and so it cannot be instantiated. We now have class Multiple implements Parser { }.

    For a work around, either do a

    1. use PhpParser\Parser\Multiple as CodeParser; or
    2. Bind the Parser interface to the concrete class Multiple so that it can be instantiated.

    I am sure you forgot to make that change. With older versions of nickic/php-parser, Parser was a concrete class. Thanks

    opened by divostar 10
  • self:: usage throws error when unserializing

    self:: usage throws error when unserializing

    I recently started using your Super Closure PHP module in our Yii 1.1 framework when implementing a worker queue. I got a problem there when I used self:: in the closures I want to serialize. In the moment the unserialized closure is called, I get a fatal PHP error:

    PHP Fatal error: Call to undefined method SuperClosure\SerializableClosure::_sendNotifications() in ~~[...]~~/common/vendor/jeremeamia/SuperClosure/src/SerializableClosure.php(153) : eval()'d code on line 2

    Let me provide some information: the closure passed looks like

            function($users) use ($push_notification,$item_id,$item_type,$link_type,$silent,$app_notification_id){
                self::_sendNotifications($users, $push_notification, $item_id, $item_type, $link_type, $silent, $app_notification_id);
            }
    

    This is how I unserialize and run the closure:

    $this->body = (new SuperClosure\Serializer())->unserialize($this->body['_payload']);
    $this->exitCode = call_user_func_array($this->body, is_array($this->params) ? $this->params : array());
    

    The serialized string contains the following:

    C:32:"SuperClosure\SerializableClosure":1113:{a:5:{s:4:"code";s:234:"function ($users) use($push_notification, $item_id, $item_type, $link_type, $silent, $app_notification_id) { self::_sendNotifications($users, $push_notification, $item_id, $item_type, $link_type, $silent, $app_notification_id); };";s:7:"context";a:6:{s:17:"push_notification";O:16:"PushNotification":12:{s:11:"page_search";N;s:19:"CActiveRecord_new";b:0;s:26:"CActiveRecord_attributes";a:7:{s:6:"status";i:3;s:16:"is_category_text";i:0;s:4:"week";i:0;s:4:"text";s:19:"guest4 followed you";s:4:"date";s:19:"2015-11-27 11:16:39";s:16:"app_notification";s:3:"314";s:2:"id";s:3:"412";}s:23:"CActiveRecord_related";a:0:{}s:17:"CActiveRecord_c";N;s:18:"CActiveRecord_pk";s:3:"412";s:21:"CActiveRecord_alias";s:1:"t";s:15:"CModel_errors";a:0:{}s:19:"CModel_validators";N;s:17:"CModel_scenario";s:6:"update";s:14:"CComponent_e";N;s:14:"CComponent_m";N;}s:7:"item_id";s:1:"1";s:9:"item_type";s:4:"user";s:9:"link_type";s:12:"user_profile";s:6:"silent";b:1;s:19:"app_notification_id";s:3:"314";}s:7:"binding";N;s:5:"scope";s:23:"PushNotificationService";s:8:"isStatic";b:1;}}
    

    I'm using the AstAnalyzer, but as I understood the documentation, it should actually work with both analyzers. I'm running on PHP 5.4.16.

    [reported in my email to @jeremeamia on 11/27, copy here for tracking reasons]

    opened by jfsalzmann 10
  • Serilization error

    Serilization error

    Hi,

    I'm using Laravel and trying to send an email with Mail::queue.

    Here's my code

    Mail::queue('emails.payment.invoice', [], function($message) use ($user, $pdf)
    {
        $message->to($user->email, $user->name);
        $message->subject('Invoice');
    
        $message->attachData($pdf, 'Invoice');
    });
    

    Underneath this uses super_closure to serialize the closure.

    But when Laravel tries to json_encode the returned serialized closure it fails with.

    http://cl.ly/image/3p29212k2M0k

    So I tried to figure out what was wrong with the UTF-8. So I used iconv -f UTF-8 input.txt -o output.txt, which gave me:

    iconv: text.txt:1:2967: cannot convert
    iconv: -o: No such file or directory
    

    The entire serialized closure can be found here: http://laravel.io/bin/lnJ93

    Any help is appreciated

    opened by andheiberg 10
  • Composer update error - update dependencies?

    Composer update error - update dependencies?

    Hi - just got this error when running composer update on a project:

    [Composer\DependencyResolver\SolverProblemsException]

    Problem 1
      - jeremeamia/SuperClosure 1.0.1 requires nikic/php-parser ~0.9 -> no matching package found.
    

    ...

    Potential causes:

    • A typo in the package name
    • The package is not available in a stable-enough version according to your minimum-stability setting see https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion for more details.

    Have other people noticed this issue? Is it possible you need to update dependencies for this project? My project is built on Laravel 4 - Laravel itself requires the nikic parser but only requires "*" rather than "~0.9". That seems to work without any problem. I'm not 100% enlightened on how composer does its business, however, so maybe I'm way off the mark.

    opened by penoonan 9
  • Fix char / string

    Fix char / string

    Using PHP 8

    1) SuperClosure\Test\Unit\SerializerTest::testUnserializingFailsWithInvalidSignature
    Only the first byte will be assigned to the string offset
    
    /dev/shm/BUILD/super_closure-5707d5821b30b9a07acfb4d76949784aaa0e9ce9/tests/Unit/SerializerTest.php:30
    
    
    opened by remicollet 8
  • Arrow functions serialization

    Arrow functions serialization

    It would be nice to have it at 7.4 final release

    https://wiki.php.net/rfc/arrow_functions

    $serializer = new SuperClosure\Serializer();
    $b = 5;
    $test = fn($a) => $a * 5;
    $c = $serializer->serialize($test);
    

    Expected: serialized closure Actual result: ClosureAnalysisException: The closure was not found within the abstract syntax tree

    opened by arokettu 8
  • Add context-free code getter for ClosureParser

    Add context-free code getter for ClosureParser

    Hi,

    This PR adds "context-free" code getter, i.e. closure's code which doesn't depend on context via $this and use (...). If it is not possible, getter raises InvalidArgumentException.

    I suppose it could be useful in case of moving closure's code to somewhere like cache with assurance that we are able to move code without breaking something.

    I'm not absolutely sure that it's OK, though.

    opened by unkind 8
Releases(2.4.0)
  • 2.4.0(Mar 21, 2018)

  • 2.3.0(Dec 7, 2016)

  • 2.2.0(Dec 5, 2015)

    What's Changed

    • Added support for PHP 7.
    • Added support for version 2.x of @nikic's PHP Parser.
    • Added a bindTo() method to SerializableClosure to match Closure's interface.
    • Replaced vendored hash_equals() implementation with the one in symfony/polyfill-php56.
    • Fixed an issue that caused the "class" value of some closures' locations to be reported incorrectly.
    • Fixed an issue with some edge cases related the closure binding and scope during unserialization.
    • Fixed an unserialization issue where SuperClosures in user variables were not being unboxed.
    • Improved error handling in the Serializer when the data being unserialized is invalid.

    Credits

    • Top Contributors
      • @GrahamCampbell :trophy:
      • @nikic :sunglasses:
      • @Remo
      • @CarsonF
    • @msarca of the opis/closure project for new discussions, ideas, and motivations.

    Lessons Learned

    It's ParseError not ParseException.

    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Mar 12, 2015)

  • 2.0.0(Jan 27, 2015)

    • Serializes closure bindings
    • Serializes recursive closures
    • Added Serializer object
      • Main class to interact with for serializing closures
      • Has special method for wrapping closures within an array/object
    • Changed the ClosureParser into ClosureAnalyzer
      • There are two kinds of analyzers:
        • AstAnalyzer - Uses PHPParser library; many features
        • TokenAnalyzer - Uses token_get_all(); fast
      • Analyzers return an array of data about a closure
    • Removed Jeremeamia from the namespace
    • Adopted PSR-4
    • Requires PHP 5.4+
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.1(Jan 20, 2015)

  • 1.0.2(Jan 12, 2015)

    Note: This is the final 1.x release.

    • Fixed #23, where "Undefined Variable Error" was being thrown for used variables whose that had a value of null.
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-alpha2(Feb 5, 2014)

    Changelog

    • There are are now 2 parses supported
      • AST Parser – Implemented with the nikic/PHPParser library. This parser is the most robust and allows you to resolve magic constants and fully-qualified class names in your closure. This is the default parser.
      • Token Parser – Implemented using the code from the old jeremeamia/FunctionParser library. This library was used in a previous version of SuperClosure, and has been ported back in. While it does not handle all edge cases like resolving magic constants, it is MUCH faster (at least an order of magnitude).
    • You can now serialize closure bindings – If you are using closures in PHP 5.4+, closures are bound to an object and scope such that you can reference $this inside of a closure. Unserialized closures from version 1 of SuperClosure needed to be rebound to an object manually to prevent failure in functions containing $this, but this version can handle bindings just fine.
    • The ability to turn features on and off – Closure parser objects accept an array of options that can allow you to configure the capability vs. performance of your closure serialization. If you don't want to serialize closure bindings or resolve magic constants, you can turn those features off.
      • Along with this is a option called turbo_mode that turns all the non-essential features off, This will make closure serialization much faster, but is the least robust at handling edge cases.
    • The easy SuperClosure\serialize() function – If you have installed SuperClosure via Composer, then the SuperClosure\serialize() function will automagically be available. This allows you to easily serialize the closure with out have to import/use any of the classes from the library directly. This function also allows you to specify the options for the parser.
    • I removed Jeremeamia from the namespace. However, there is a class alias automatically specified for the SerializableClosure class to maintain some backwards compatibility. You can use either SuperClosure\SerializableClosure or Jeremeamia\SuperClosure\SerializableClosure.
    • The package is now PSR-4 compliant.

    Is everything different and broken?

    It depends. Mostly no.

    If you were just using the SerializableClosure object, then it should work exactly the same way as before.

    $closure = new SerializableClosure($closure);
    $serialized = serialize($closure);
    

    If you were relying directly on the ClosureParser object, then you will have breaking changes for sure. They likely will not be difficult to fix though since SuperClosure is still a small library. Just keep in mind that there is now more than one type of parser available.

    Examples

    use SuperClosure\SerializableClosure;
    use SuperClosure\ClosureParser\Options;
    use SuperClosure\ClosureParser\Ast\AstParser;
    use SuperClosure\ClosureParser\Token\TokenParser;
    
    // TRADITIONAL MODE (Same as in v1.0; uses "ROBUST MODE")
    $closure = new SerializableClosure($closure);
    $serialized = serialize($closure);
    
    // ROBUST MODE (i.e., SLOW MODE) (Uses the AST parser with all features on)
    $serialized = SuperClosure\serialize($closure);
    
    // TURBO MODE (Uses the token parser, with all features off)
    $serialized = SuperClosure\serialize($closure, array(Options::TURBO_MODE => true));
    
    // The rest are examples of mixing and matching features
    //-------------------------------------------------------
    
    // Does everything else, but ignores closure bindings
    // This is perfect for functions in PHP 5.4+ that are declared in a class, but do not reference `$this`
    $serialized = SuperClosure\serialize($closure, array(
        Options::HANDLE_CLOSURE_BINDINGS => false,
    ));
    
    // Uses the Token parser implicitly, by disabling the features unique to the AST parser
    $serialized = SuperClosure\serialize($closure, array(
        Options::HANDLE_MAGIC_CONSTANTS => false,
        Options::HANDLE_CLASS_NAMES     => false,
    ));
    
    // Uses the Token parser explicitly
    $serialized = SuperClosure\serialize($closure, new TokenParser);
    
    // This is equivalent to TURBO MODE. ZOOOOOOM!!!
    $options = new Options(array(Options::VALIDATE_TOKENS => false));
    $serialized = SuperClosure\serialize($closure, new TokenParser($options)));
    

    TODO

    • Unit Tests - I removed all of the previous unit tests due to the extreme changes. However, I currently have a suite of integration tests that exercise the code nicely and show how it handles different scenarios. I plan on adding the unit tests back before the stable release.
    • Documentation - A lot of the docblocks are missing, incomplete, or out of date. I'll work on fixing these us before the stable release as well.
    Source code(tar.gz)
    Source code(zip)
  • 2.0-alpha1(Jan 14, 2014)

    SuperClosure is getting an overhaul!

    Changelog

    • There are are now 2 parses supported
      • AST Parser – Implemented with the nikic/PHPParser library. This parser is the most robust and allows you to resolve magic constants and fully-qualified class names in your closure. This is the default parser.
      • Token Parser – Implemented using the code from the old jeremeamia/FunctionParser library. This library was used in a previous version of SuperClosure, and has been ported back in. While it does not handle all edge cases like resolving magic constants, it is MUCH faster (at least an order of magnitude).
    • You can now serialize closure bindings – If you are using closures in PHP 5.4+, closures are bound to an object and scope such that you can reference $this inside of a closure. Unserialized closures from version 1 of SuperClosure needed to be rebound to an object manually to prevent failure in functions containing $this, but this version can handle bindings just fine.
    • The ability to turn features on and off – Closure parser objects accept an array of options that can allow you to configure the capability vs. performance of your closure serialization. If you don't want to serialize closure bindings or resolve magic constants, you can turn those features off.
      • Along with this is a option called turbo_mode that turns all the non-essential features off, This will make closure serialization much faster, but is the least robust at handling edge cases.
    • The easy serialize_closure() function – If you have installed SuperClosure via Composer, then the serialize_closure() function will automagically be available. This allows you to easily serialize the closure with out have to import/use any of the classes from the library directly. This function also allows you to specify the options for the parser.
    • The package is now PSR-4 compliant. As soon as TravisCI is ready and Jordi (Composer author) gives the PHP world the green light, I'll remove the provided autoload.php in favor of Composer's PSR-4 support.

    Is everything different and broken?

    It depends. Mostly no.

    If you were just using the SerializableClosure object, then it should work exactly the same way as before.

    $closure = new SerializableClosure($closure);
    $serialized = serialize($closure);
    

    If you were relying directly on the ClosureParser object, then you will have breaking changes for sure. They likely will not be difficult to fix though since SuperClosure is still a small library. Just keep in mind that there is now more than one type of parser available.

    Examples

    // ROBUST MODE (i.e., SLOW MODE) (Uses the AST parser with all features on)
    $serialized = serialize_closure($closure);
    
    // TURBO MODE (Uses the token parser, with all features off)
    $serialized = serialize_closure($closure, array(SC_TURBO_MODE => true));
    
    // The rest are examples of mixing and matching features
    //-------------------------------------------------------
    
    // Does everything else, but ignores closure bindings
    // This is perfect for functions in PHP 5.4+ that are declared in a class, but do not reference `$this`
    $serialized = serialize_closure($closure, array(
        SC_HANDLE_CLOSURE_BINDINGS => false,
    ));
    
    // Uses the Token parser explicitly
    $serialized = serialize_closure($closure, array(
        SC_PARSER_CLASS => SC_PARSER_TOKEN,
    ));
    
    // Uses the Token parser implicitly, by disabling the features unique to the AST parser
    $serialized = serialize_closure($closure, array(
        SC_HANDLE_MAGIC_CONSTANTS => false,
        SC_HANDLE_CLASS_NAMES     => false,
    ));
    
    // This is equivalent to TURBO MODE. ZOOOOOOM!!!
    $serialized = serialize_closure($closure, array(
        SC_PARSER_CLASS    => SC_PARSER_TOKEN,
        SC_VALIDATE_TOKENS => false,
    ));
    

    TODO

    • Unit Tests - I removed all of the previous unit tests due to the extreme changes. However, I currently have a suite of integration tests that exercise the code nicely and show how it handles different scenarios.
    • Collect Feedback - I've made a lot of changes. I'd love to hear what you think. Do you like the changes? Do the config settings make sense? Do the config defaults work well? Let me know if you have any suggestions, feedback, ideas, complaints, etc.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Oct 9, 2013)

Owner
Jeremy Lindblom
Principle Software Engineer at McGraw-Hill Education. OSS contributor, conference speaker, & community organizer in the PHP community. <3 OSS, PHP, APIs, & AWS
Jeremy Lindblom
This is a library to serialize PHP variables in JSON format

This is a library to serialize PHP variables in JSON format. It is similar of the serialize() function in PHP, but the output is a string JSON encoded. You can also unserialize the JSON generated by this tool and have you PHP content back.

Zumba 118 Dec 12, 2022
PHP remote closure executor

Jumper Allow you to execute PHP Closure in other distant computer via SSH and without client/server setup. Source computer dependency: PHP >= 5.3 (so

Thibaud Lepretre 45 Aug 11, 2022
This is the official place where Nemesysco's LVA7 and QA7 dockers will be hosted and maintained

LVA-Dockers This is the official place where Nemesysco's LVA7 and QA7 dockers will be hosted and maintained - It is still under construction! We are w

null 2 Feb 17, 2022
This component provides a collection of functions/classes using the symfony/intl package when the Intl extension is not installed.

Symfony Polyfill / Intl: ICU This package provides fallback implementations when the Intl extension is not installed. It is limited to the "en" locale

Symfony 2.4k Jan 6, 2023
This is an experiment to export all RFCs from the PHP wiki into Git, including the change history for each RFC (along with the date and author of each change). This is not meant to replace the wiki.

PHP Requests for Comments (RFCs) About This repository is an experiment to export all RFCs from the PHP wiki into Git, including the change history fo

Ben Ramsey 34 Jun 20, 2022
This is a plugin for pocketmine-mp, when locking a player's items helps players not to lose items or throw things around causing server lag.

[] LockedItem| v1.0.0 Player's item lock Features Player's item lock Players aren't afraid of losing items For Devolopers You can access to LockedItem

JeroGamingYT 3 Jan 4, 2022
Magento 2 Module Experius Page Not Found 404. This module saves all 404 url to a database table

Magento 2 Module Experius Page Not Found 404 This module saves all 404 urls to a database table. Adds an admin grid with 404s It includes a count so y

Experius 28 Dec 9, 2022
Magento commands to find translations that are present in one CSV file but not in another, and to translate CSV dicts with DeepL

Hyvä Themes - Magento translation CSV comparison command hyva-themes/magento2-i18n-csv-diff This module adds the bin/magento i18n:diff-csv and i18n:tr

Hyvä 6 Oct 26, 2022
Allows installing Drupal extensions event if not compatible with installed drupal/core package

mglaman/composer-drupal-lenient Lenient with it, Drupal 10 with it. Why? The Drupal community introduced a lenient Composer facade that modified the d

Matt Glaman 14 Dec 18, 2022
Keep control over the complexity of your methods by checking that they do not have too many arguments.

php arguments detector The ideal number of arguments for a function is zero. ~ Robert C. Martin Keep control over the complexity of your methods by ch

DeGraciaMathieu 13 Dec 26, 2022
This repository demonstrates exemplary implementation of chat using HTTP and Websocket servers in PHP using Kraken Framework components.

This repository demonstrates exemplary implementation of chat using HTTP and Websocket servers in PHP using Kraken Framework components.

Kraken 48 Aug 11, 2021
A research raw data repository for researchers of Arba Minch University built using Codeigniter which follows MVC architecture. The front-end is build using Bootstrap.

Arba Minch University Dataset Repository This system is a research dataset repository for Arba Minch University researchers and is build using Codeign

Wuletaw Wonte 8 Jul 1, 2022
Nuber is an open source container management platform it provides a front end to manage your own cloud infrastructure, using Linux Containers virtualization technology

Nuber is an open source container management platform it provides a front end to manage your own cloud infrastructure, using Linux Containers virtualization technology

null 33 Dec 14, 2022
A PHP library to convert text to speech using various services

speaker A PHP library to convert text to speech using various services

Craig Duncan 98 Nov 27, 2022
Laradeploy offers you to automate deployment using a GitHub webhook.

Introduction Laradeploy offers you to automate deployment using a GitHub webhook. Simple and fast just make a git push to GitHub deploy the new modifi

Gentrit Abazi 10 Feb 21, 2022
Xenon\LaravelBDSms is a sms gateway package for sending text message to Bangladeshi mobile numbers using several gateways like sslcommerz, greenweb, dianahost,metronet in Laravel framework

Xenon\LaravelBDSms is a sms gateway package for sending text message to Bangladeshi mobile numbers using several gateways for Laravel. You should use

Ariful Islam 95 Jan 3, 2023
Rafel is Remote Access Tool Used to Control Victims Using WebPanel With More Advance Features..

Rafel is Remote Access Tool Used to Control Victims Using WebPanel With More Advance Features..

swagkarna 690 Dec 28, 2022
This is a PocketMine plugin that helps staffs track players using commands.

Track This is a PocketMine plugin that helps staffs track players using commands. Features Allows selected staffs to watch players use commands to fac

Nguyễn Thành Nhân 6 Jun 23, 2022