Компонент VarDumper (сброс переменной)

Дата обновления перевода 2023-01-19

Компонент VarDumper (сброс переменной)

Компонент VarDumper предоставляет механизмы для извлечения состояния из любой переменной PHP. Так как он надстраивается, он предоставляет улучшенную функцию dump(), которую вы можете использовать вместо var_dump.

Установка

1
$ composer require symfony/var-dumper --dev

Note

Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно подключить файл vendor/autoload.php в вашем коде для включения механизма автозагрузки классов, предоставляемых Composer. Детальнее читайте в этой статье.

Note

Если вы используете его внутри приложения Symfony, убедитесь, что был установлен DebugBundle (или запустите composer require symfony/debug-bundle, чтобы установить его).

Функция dump()

Компонент VarDumper создаёт глобальную функцию dump(), которую вы можете использовать вместо, например. var_dump. Используя её, вы получаете:

  • Специализированный просмотр по объектам и источникам, чтобы, к примеру, отфильтровать внутренние объекты Doctrine при сбросе одной сущности прокси, или получить больше информации об открытых с помощью stream_get_meta_data файлах;
  • Конфигурируемые форматы вывода: вывод HTML или цветной командной строки;
  • Возможность сбрасывать внутренние ссылки, мягкие (объекты или источники) или жёсткие (=& в свойствах массивов или объектов). Повторяемое появление одного и того же объекта/масива/истоничка не будут больше появляться снова и снова. Более того, вы сможете исследовать структуру ссылок ваших данных;
  • Возможность оперировать в контексте обработчика буферизации вывода.

Например:

1
2
3
4
5
6
7
8
9
require __DIR__.'/vendor/autoload.php';

// создать переменную, которая может быть чем угодно!
$someVar = ...;

dump($someVar);

// dump() возвращает переданное значение, чтобы вы могли сбросить объект и продолжать использовать его
dump($someObject)->someMethod();

По умолчанию, формат вывода и направление выбираются исходя из вашего текущего PHP SAPI:

  • В командной строке (CLI SAPI), вывод пишется в STDOUT. Это может быть удивительно для некоторых, так как это обходит механизм буферизации вывода PHP;
  • В других SAPI, сбросы пишутся в виде HTML в обычном выводе.

Tip

Вы также можете выбрать формат вывода ясно, определив переменную окружения VAR_DUMPER_FORMAT и установив её значение как html, cli или сервер .

Note

Если вы хотите поймать вывод сброса в виде строки, пожалуйста, прочтите продвинутую документацию, которая содержит такие примеры. Вы также узнаете, как изменять формат или перенаправлять вывод туда, куда вам нужно.

Tip

Для того, чтобы функция dump() всегда была доступна при выполнении любого PHP кода, вы можете установить её на вашем компьютере глобально:

  1. Запустите composer global require symfony/var-dumper;
  2. Добавьте auto_prepend_file = ${HOME}/.composer/vendor/autoload.php к вашему файлу php.ini;
  3. Иногда запускайте composer global update symfony/var-dumper, чтобы иметь последние исправления багов.

Tip

Компонент VarDumper также предоставляет функцию dd() ("dump and die" - "сбрось и умри"). Эта функция отображает переменные используя dump() и сразу прекращает исполнение скрипта (используя функцию PHP exit).

Сервер сброса

Функция dump() выводит своё содержание в то же окно браузера или консольный терминал, что и ваше приложение. Иногда смешение настоящего вывода с выводом отладочной информации может запутывать. Поэтому этот компонент предоставляет сервер для сбора всей отладочной информации.

Запустите сервер командой server:dump и когда вы будете вызывать dump(), отладочная информация не будет отображаться в потоке вывода, а отправится на этот сервер, который будет отображать это в своей конслоли или HTML-файле:

1
2
3
4
5
6
# отображает отладочную информацию в консоли:
$ ./bin/console server:dump
  [OK] Server listening on tcp://0.0.0.0:9912

# сохраняет отладочную информацию в файле используя формат HTML:
$ ./bin/console server:dump --format=html > dump.html

Внути приложения Symfony, вывод сервера сброса настраивается с помощью настройки dump_destination пакета debug:

  • YAML
  • XML
  • PHP
1
2
3
# config/packages/debug.yaml
debug:
   dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"

Вне приложения Symfony, используйте класс ServerDumper:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require __DIR__.'/vendor/autoload.php';

use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider;
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Dumper\ServerDumper;
use Symfony\Component\VarDumper\VarDumper;

$cloner = new VarCloner();
$fallbackDumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg']) ? new CliDumper() : new HtmlDumper();
$dumper = new ServerDumper('tcp://127.0.0.1:9912', $fallbackDumper, [
    'cli' => new CliContextProvider(),
    'source' => new SourceContextProvider(),
]);

VarDumper::setHandler(function ($var) use ($cloner, $dumper) {
    $dumper->dump($cloner->cloneVar($var));
});

Note

Второй аргумент ServerDumper - это класс экземпляра DataDumperInterface, используемый в качестве резерва, когда сервер недоступен. Третий аргумент - это поставщики контекста, которые позволяют собрать некоторую информацию о контексте, в котором были сброшены данные. Встроенные поставщики контекста: cli, request и source.

Затем вы можете использовать следующую команду, чтобы запустить сервер сразу же:

1
2
$ ./vendor/bin/var-dump-server
  [OK] Server listening on tcp://127.0.0.1:9912

Конфигурация сервера сброса с переменными окружения

Если вы предпочитаете не изменять конфигурацию приложения (например, чтобы быстро отладить данный вам проект), используйте переменную окружения VAR_DUMPER_FORMAT.

Сначала, запустите сервер как обычно:

1
$ ./vendor/bin/var-dump-server

Затем, запустите ваш код с переменной окружения VAR_DUMPER_FORMAT=server, сконфигурировав это значение в файле .env вашего приложения. Для консольных команд вы также можете определить эту переменную окружения так:

1
$ VAR_DUMPER_FORMAT=server [your-cli-command]

Note

Хост, использумый форматом server, тот, что сконфигурирован в переменной окружения VAR_DUMPER_SERVER или 127.0.0.1:9912, если он не определён. Если вы хотите, вы также можете сконфигурировать хост в переменной окружения VAR_DUMPER_FORMAT таким образом: VAR_DUMPER_FORMAT=tcp://127.0.0.1:1234.

Интеграция DebugBundle и Twig

DebugBundle позволяет большую интеграцию компонента в приложения Symfony.

Так как генрировние вывода (даже отладки) в контроллере или модели вашего приложения может просто его сломать (например, отправка HTTP заголовков или нарушение вашего просмотра), пакет конфигурирует функцию dump(), чтобы переменные сбрасывались в панели инструментов веб-отладки.

Но если панель инструментов нельзя отобразить так как вы, к примеру, вызвали die()/exit()/dd() или возникла фатальная ошибка, тогда сбросы пишутся в обычном потоке вывода.

В шаблоне Twig доступны две конструкции для сброса переменной. Выбор между двумя в основном зависит от ваших личных предпочтейни, и всё же:

  • {% dump foo.bar %} стоит использовать, когда исходный вывод шаблона не стоит изменять: переменные сбрасываются не встроено, а в панели инструментов веб отладки;
  • и наоборот, {{ dump(foo.bar) }} сбрастывает встроено и поэтому может подходить или не подходить в вашем случае (например, не стоит использовать его в атрибуте HTML или теге <script>).

Это поведение можно изменить, сконфигурировав опцию debug.dump_destination. Прочтите больше об этом и других опциях в справочнике конфигурации DebugBundle.

Tip

Если сброшенное содержание сложное, рассмотрите использование локального окна поиска, чтобы найти конкретные переменные или значения. Для начала, нажмите где угодно в сброшенном содержании, а затем нажмите Ctrl. + F или Cmd. + F, чтобы появилось локальное окно поиска. Поддерживаются все распространённые сокращения для навигации по результатам поиска (Ctrl. + G или Cmd. + G, F3 и т.д.). Когда вы закончите, нажмите Esc., чтобы снова спрятать окно.

Если вы хотите использовать ввод поиска вашего браузера, нажмите Ctrl. + F или Cmd. + F снова, фокусируясь на вводе поиска VarDumper.

Использование компонента VarDumper в вашем наборе тестов PHPUnit

Компонент VarDumper предоставляет черту, который может помочь написать некоторые из ваших тестов для PHPUnit.

Это предоставит вам два новых утверждения:

assertDumpEquals()
верифицирует, чтобы сброс переменной, данный в виде второго аргументы, соответствовал ожидаемому сбросу, предоставленному в качестве первого аргумента.
assertDumpMatchesFormat()
такой же, как и предыдущий метод, но принимает заполнители в ожидаемом сбросе, основанном на методе assertStringMatchesFormat(), предоставленном PHPUnit.

VarDumperTestTrait также содержит такие другие методы:

setUpVarDumper()
используется для конфигурации доступных кастеров и их опций, что является способом только контроля полей, которые вы ожидаете, и позволяет написание кратких тестов.
tearDownVarDumper()
вызывается автоматически после каждого случая, чтобы перезагрузить пользовательскую конфигурацию, сделанную в setUpVarDumper().

Пример:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use PHPUnit\Framework\TestCase;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;

class ExampleTest extends TestCase
{
    use VarDumperTestTrait;

    protected function setUp()
    {
        $casters = [
            \DateTimeInterface::class => static function (\DateTimeInterface $date, array $a, Stub $stub): array {
                $stub->class = 'DateTime';
                return ['date' => $date->format('d/m/Y')];
            },
        ];

        $flags = CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR;

        // это конфигурирует кастеры и флаги для использования во всех тестах этого класса.
        // Если вам нужны пользовательские конфигурации для каждого теста, а не для всего класса,
        // лушче вызовите этот метод setUpVarDumper() из этих тестов.
        $this->setUpVarDumper($casters, $flags);
    }

    public function testWithDumpEquals()
    {
        $testedVar = [123, 'foo'];

        // ожидаемое содержание сброса не имеет структуры VarDumper по умолчанию
        // из-за пользовательских кастеров и флагов, использованных в тесте
        $expectedDump = <<<EOTXT
[
  123,
  "foo",
]
EOTXT;

        // если первый аргумент - строка, он должен быть полным ожидаемым сбросом
        $this->assertDumpEquals($expectedDump, $testedVar);

        // если первый аргумент - не строка, assertDumpEquals() сбрасывает его и
        // сравнивает его со сбросом второго аргумента
        $this->assertDumpEquals($testedVar, $testedVar);
    }
}

Примеры сброса и вывод

Для простых переменных, чтение вывода должно быть прямолинейным. Вот некоторые примеры, отображающие первую переменную, определённую в PHP, а потом его представление сброса:

1
2
3
4
5
6
7
8
$var = array(
    'a simple string' => "in an array of 5 elements",
    'a float' => 1.0,
    'an integer' => 1,
    'a boolean' => true,
    'an empty array' => array(),
);
dump($var);

Note

Серая стрелка - это кнопка переключателя для показа / скрытия детей встроенных структур.

1
2
3
4
5
6
7
$var = "Это многострочная строка.\n";
$var .= "Наведение на строку показывает её длину.\n";
$var .= "Длина UTF-8 строк считается в рамках символов UTF-8.\n";
$var .= "Длина не-UTF-8 строк считается октетами.\n";
$var .= "Из-за этого `\xE9` октет (\\xE9),\n";
$var .= "Эта строка не UTF-8 валидна,  поэтому `b` prefix.\n";
dump($var);
1
2
3
4
5
6
7
8
9
class PropertyExample
{
    public $publicProperty = 'The `+` prefix denotes public properties,';
    protected $protectedProperty = '`#` protected ones and `-` private ones.';
    private $privateProperty = 'Hovering a property shows a reminder.';
}

$var = new PropertyExample();
dump($var);

Note

`#14` это внутренний объект для обработки. Он позволяет сранвивать два последовательных сброса одного и того же объекта.

1
2
3
4
5
6
7
8
class DynamicPropertyExample
{
    public $declaredProperty = 'Это свойство объявлено в определении класса';
}

$var = new DynamicPropertyExample();
$var->undeclaredProperty = 'Runtime added dynamic properties have `"` around their name.';
dump($var);
1
2
3
4
5
6
7
class ReferenceExample
{
    public $info = "Цикличные и родственные ссылки отображаются, как `#number`.\n Наведение на них выделяет все экземпляры в одном сбросе.\n";
}
$var = new ReferenceExample();
$var->aCircularReference = $var;
dump($var);
1
2
3
4
5
6
7
8
$var = new \ErrorException(
    "Для некоторых объектов свойства имеют специальные значения,\n"
    ."которые лучше всего отображаются в виде ограничений, вроде\n"
    ."`severity` ниже. Наведение на них отображает значение (`2`).\n",
    0,
    E_WARNING
);
dump($var);
1
2
3
4
5
6
7
8
$var = array();
$var[0] = 1;
$var[1] =& $var[0];
$var[1] += 1;
$var[2] = array("Hard references (circular or sibling)");
$var[3] =& $var[2];
$var[3][] = "are dumped using `&number` prefixes.";
dump($var);
1
2
3
4
5
$var = new \ArrayObject();
$var[] = "Некоторые источники и специальные объекты, как текущий";
$var[] = "иногда лучше всего представить, используя виртуальные";
$var[] = "свойства, описывающие их внутреннее сстояние.";
dump($var);
1
2
3
4
5
6
7
8
$var = new AcmeController(
    "Когда сброс превышает максимальный лимит объектов,\n"
    ."или когда встречаются специальные объекты,\n"
    ."дети могут быть заменены эллипсами и\n"
    ."опционально иметь число, которое сообщает как\n"
    ."и сколько было удалено; В этом случае `9`.\n"
);
dump($var);