Компонент VarExporter
Дата обновления перевода 2022-01-03
Компонент VarExporter
Компонент VarExporter экспортирует всю структуру PHP-данных, поддающуюся сериализации, в чистый PHP-код и позволяет инстанциировать и населять объекты без вызова к их конструкторам.
Установка
1
$ composer require --dev symfony/var-exporter
Note
Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно
подключить файл vendor/autoload.php
в вашем коде для включения механизма
автозагрузки классов, предоставляемых Composer. Детальнее читайте в
этой статье.
Экспорт/сериализация переменных
Главная функция этого компонента - сериализовать структуры PHP-данных в чистый PHP-код, схоже в функцией PHP var_export:
1 2 3 4 5 6 7 8
use Symfony\Component\VarExporter\VarExporter;
$exported = VarExporter::export($someVariable);
// сохраните $exported данные в каком-то файле или системе кеширования для дальнейшего повторного использования
$data = file_put_contents('exported.php', $exported);
// позже, регенерируйте изначальную переменную, когда она вам понадобится
$regeneratedVariable = require 'exported.php';
Причина использования этого компонента вместо serialize()
или igbinary
кроется
в производительности: благодаря OPcache, итоговый код значительно быстрее и более
эффективный с точки зрения памяти, чем при использовании unserialize()
или igbinary_unserialize()
.
Кроме этого, есть некоторые небольшие различия:
- Если изначальная переменная это определяет, вся семантика, ассоциированная с
serialize()
(такая как__wakeup()
,__sleep()
, иSerializable
) сохраняется (var_export()
игнорирует это); - Ссылки, задействующие экземпляры
SplObjectStorage
,ArrayObject
илиArrayIterator
сохраняются; - Отсутствующие классы вызывают
ClassNotFoundException
вместо десериализации в объектыPHP_Incomplete_Class
; - Классы
Reflection*
,IteratorIterator
иRecursiveIteratorIterator
вызывают исключение при попытке сериализации.
Экспортированный данные - это PSR-2, совместимый с PHP-файлом. Рассмотрите, к примеру, следующую иерархию классов:
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);
}
}
При экспорте данных ConcreteClass
с помощью VarExporter, сгенерированный PHP-файл
выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?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],
[]
);
Инстанциация PHP-классов
Другой основной функцией, предоставленной этим компонентом, является формирователь, который может создавать объекты и устанавливать их свойства без вызова их конструкторов или любых других методов:
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\VarExporter\Instantiator;
// создает пустой экземпляр Foo
$fooObject = Instantiator::instantiate(Foo::class);
// создает экземпляр Foo и устанавливает одно из его свойств
$fooObject = Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]);
// создает экземпляр Foo и устанавливает частное свойство, определенное в его родительском классе Bar
$fooObject = Instantiator::instantiate(Foo::class, [], [
Bar::class => ['privateBarProperty' => $propertyValue],
]);
Экземпляры ArrayObject
, ArrayIterator
и SplObjectHash
могут быть созданы
используя специальное имя свойства "\0"
для определения их внутреннего значения:
1 2 3 4 5 6 7 8 9
// Создает SplObjectHash, где $info1 ассоциируется с $object1, и т.д.
$theObject = Instantiator::instantiate(SplObjectStorage::class, [
"\0" => [$object1, $info1, $object2, $info2...],
]);
// создает ArrayObject, населенный $inputArray
$theObject = Instantiator::instantiate(ArrayObject::class, [
"\0" => [$inputArray],
]);