The VarExporter Component
The VarExporter component exports any serializable PHP data structure toplain PHP code and allows to instantiate and populate objects withoutcalling their constructors.
Installation
- $ composer require --dev symfony/var-exporter
Note
If you install this component outside of a Symfony application, you mustrequire the vendor/autoload.php
file in your code to enable the classautoloading mechanism provided by Composer. Readthis article for more details.
Exporting/Serializing Variables
The main feature of this component is to serialize PHP data structures to plainPHP code, similar to PHP's var_export
function:
- use Symfony\Component\VarExporter\VarExporter;
- $exported = VarExporter::export($someVariable);
- // store the $exported data in some file or cache system for later reuse
- $data = file_put_contents('exported.php', $exported);
- // later, regenerate the original variable when you need it
- $regeneratedVariable = require 'exported.php';
The reason to use this component instead of serialize()
or igbinary
isperformance: thanks to OPcache, the resulting code is significantly fasterand more memory efficient than using unserialize()
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()
, andSerializable
)are preserved (var_export()
ignores them); - References involving
SplObjectStorage
,ArrayObject
orArrayIterator
instances are preserved; - Missing classes throw a
ClassNotFoundException
instead of beingunserialized toPHP_Incomplete_Class
objects; Reflection*
,IteratorIterator
andRecursiveIteratorIterator
classes throw an exception when being serialized.The exported data is a PSR-2 compatible PHP file. Consider for example thefollowing class hierarchy:
- abstract class AbstractClass
- {
- protected $foo;
- private $bar;
- protected function setBar($bar)
- {
- $this->bar = $bar;
- }
- }
- class ConcreteClass extends AbstractClass
- {
- public function __construct()
- {
- $this->foo = 123;
- $this->setBar(234);
- }
- }
When exporting the ConcreteClass
data with VarExporter, the generated PHPfile looks like this:
- <?php
- return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
- $o = [
- clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\ConcreteClass'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\ConcreteClass')),
- ],
- null,
- [
- 'Symfony\\Component\\VarExporter\\Tests\\AbstractClass' => [
- 'foo' => [
- 123,
- ],
- 'bar' => [
- 234,
- ],
- ],
- ],
- $o[0],
- []
- );
Instantiating PHP Classes
The other main feature provided by this component is an instantiator which cancreate objects and set their properties without calling their constructors orany other methods:
- use Symfony\Component\VarExporter\Instantiator;
- // creates an empty instance of Foo
- $fooObject = Instantiator::instantiate(Foo::class);
- // creates a Foo instance and sets one of its properties
- $fooObject = Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]);
- // creates a Foo instance and sets a private property defined on its parent Bar class
- $fooObject = Instantiator::instantiate(Foo::class, [], [
- Bar::class => ['privateBarProperty' => $propertyValue],
- ]);
Instances of ArrayObject
, ArrayIterator
and SplObjectHash
can becreated by using the special "\0"
property name to define their internal value:
- // Creates an SplObjectHash where $info1 is associated to $object1, etc.
- $theObject = Instantiator::instantiate(SplObjectStorage::class, [
- "\0" => [$object1, $info1, $object2, $info2...]
- ]);
- // creates an ArrayObject populated with $inputArray
- $theObject = Instantiator::instantiate(ArrayObject::class, [
- "\0" => [$inputArray]
- ]);