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 2 3 4 5 6 7 8
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', '<?php return '.$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
is
performance: thanks to OPcache, the resulting code is significantly faster
and 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 as__wakeup()
,__sleep()
, andSerializable
) are preserved (var_export()
ignores them); - References involving
SplObjectStorage
,ArrayObject
orArrayIterator
instances are preserved; - Missing classes throw a
ClassNotFoundException
instead of being unserialized 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 the following class hierarchy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
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 PHP
file looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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 can create objects and set their properties without calling their constructors or any other methods:
1 2 3 4 5 6 7 8 9 10 11 12
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 be
created by using the special "\0"
property name to define their internal value:
1 2 3 4 5 6 7 8 9
// Creates an SplObjectHash where $info1 is associated with $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],
]);