The VarExporter Component

The VarExporter Component

The VarExporter component exports any serializable PHP data structure to plain PHP code and allows to instantiate and populate objects without calling their constructors.

Installation

  1. $ composer require --dev symfony/var-exporter

Note

If you install this component outside of a Symfony application, you must require the vendor/autoload.php file in your code to enable the class autoloading mechanism provided by Composer. Read this article for more details.

Exporting/Serializing Variables

The main feature of this component is to serialize PHP data structures to plain PHP code, similar to PHP’s var_export function:

  1. use Symfony\Component\VarExporter\VarExporter;
  2. $exported = VarExporter::export($someVariable);
  3. // store the $exported data in some file or cache system for later reuse
  4. $data = file_put_contents('exported.php', $exported);
  5. // later, regenerate the original variable when you need it
  6. $regeneratedVariable = require 'exported.php';

The reason to use this component instead of serialize() origbinaryis performance: thanks to [OPcache](https://www.php.net/opcache), the resulting code is significantly faster and more memory efficient than usingunserialize() or `igbinary_unserialize().

In addition, there are some minor differences:

  • If the original variable defines them, all the semantics associated with serialize() (such aswakeup(), `sleep(), and Serializable) are preserved (`var_export() ignores them);
  • References involving SplObjectStorage, ArrayObject or ArrayIterator instances are preserved;
  • Missing classes throw a ClassNotFoundException instead of being unserialized to PHP_Incomplete_Class objects;
  • Reflection*, IteratorIterator and RecursiveIteratorIterator classes throw an exception when being serialized.

The exported data is a PSR-2 compatible PHP file. Consider for example the following class hierarchy:

  1. abstract class AbstractClass
  2. {
  3. protected $foo;
  4. private $bar;
  5. protected function setBar($bar)
  6. {
  7. $this->bar = $bar;
  8. }
  9. }
  10. class ConcreteClass extends AbstractClass
  11. {
  12. public function __construct()
  13. {
  14. $this->foo = 123;
  15. $this->setBar(234);
  16. }
  17. }

When exporting the ConcreteClass data with VarExporter, the generated PHP file looks like this:

  1. <?php
  2. return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
  3. $o = [
  4. clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\ConcreteClass'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\ConcreteClass')),
  5. ],
  6. null,
  7. [
  8. 'Symfony\\Component\\VarExporter\\Tests\\AbstractClass' => [
  9. 'foo' => [
  10. 123,
  11. ],
  12. 'bar' => [
  13. 234,
  14. ],
  15. ],
  16. ],
  17. $o[0],
  18. []
  19. );

Instantiating PHP Classes

The other main feature provided by this component is an instantiator which can create objects and set their properties without calling their constructors or any other methods:

  1. use Symfony\Component\VarExporter\Instantiator;
  2. // creates an empty instance of Foo
  3. $fooObject = Instantiator::instantiate(Foo::class);
  4. // creates a Foo instance and sets one of its properties
  5. $fooObject = Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]);
  6. // creates a Foo instance and sets a private property defined on its parent Bar class
  7. $fooObject = Instantiator::instantiate(Foo::class, [], [
  8. Bar::class => ['privateBarProperty' => $propertyValue],
  9. ]);

Instances of ArrayObject, ArrayIterator and SplObjectHash can be created by using the special "\0" property name to define their internal value:

  1. // Creates an SplObjectHash where $info1 is associated to $object1, etc.
  2. $theObject = Instantiator::instantiate(SplObjectStorage::class, [
  3. "\0" => [$object1, $info1, $object2, $info2...]
  4. ]);
  5. // creates an ArrayObject populated with $inputArray
  6. $theObject = Instantiator::instantiate(ArrayObject::class, [
  7. "\0" => [$inputArray]
  8. ]);

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.