Компонент VarExporter

Дата оновлення перекладу 2022-11-17

Компонент 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],
]);