Компонент Yaml
Дата обновления перевода 2024-07-10
Компонент Yaml
Компонент Yaml загружает и сбрасывает файлы YAML.
Что это?
Компонент Symfony Yaml анализирует YAML строки, чтобы преобразовать их в PHP массивы. Он также может преобразовывать PHP массивы в YAML строки.
YAML, YAML не является языком разметки - это дружелюбный стандарт сериализации данных для всех языков программирования. YAML является отличным форматом для ваших файлов конфигурации. Файлы YAML так же экспрессивны, как файлы XML, и так же читаемы, как файлы INI.
Tip
Узнайте больше о спецификациях YAML.
Установка
1
$ composer require symfony/yaml
Note
Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно
подключить файл vendor/autoload.php
в вашем коде для включения механизма
автозагрузки классов, предоставляемых Composer. Детальнее читайте в
этой статье.
Почему?
Скорость
Одна из целей Symfony Yaml - найти правильный баланс между скоростью и функциональностью. Он поддерживает только необходимые функции для обработки файлов конфигурации. Не хватает таких заметных функций: директив документов, многострочных цитируемых сообщений, компактных коллекций блоков и многодокументных файлов.
Реальный парсер
Поддерживает реальный парсер и понимает большую часть спецификации YAML для всех ваших потребностей конфигурации. Это также означает, что парсер достаточно обширен, легок в понимании и достаточно прост для расширения.
Ясные сообщения ошибок
Каждый раз, когда у вас есть проблема синтаксиса в ваших YAML файлах, библиотека выводит полезное сообщение с именем файла и номером строки, где возникла проблема. Это очень облегчает отладку.
Поддержка сброса
Он также может сбрасывать PHP массивы в YAML с поддержкой объектов, и встраиваемый уровень конфигурации для красивых выводов.
Поддержка типов
Поддерживает большинство встроенных типов YAML вроде дат, целых чисел, чисел в восьмеричной системе, булевых значений и многие другие...
Поддержка ключей полного слияния
Полная поддержка ссылок, дополнительных имён и ключей полного слияния. Не повторяйте самостоятельно, ссылаясь на распространённые части конфигурации.
Использование компонента Symfony YAML
Компонент Symfony Yaml состоит из двух главных классов: один анализирует YAML строки (Parser), а второй - сбрасывает PHP массив в строку YAML (Dumper).
Поверх этих двух классов, класс Yaml работает как тонкая прослойка и упрощает частые варианты использования.
Чтение содержания YAML
Метод parse() анализирует строку YAML и преобразует её в PHP массив:
1 2 3 4
use Symfony\Component\Yaml\Yaml;
$value = Yaml::parse("foo: bar");
// $value = ['foo' => 'bar']
Если ошибка возникает во время анализа, парсер вызывает исключение ParseException, показывая тип ошибки и строчку исходной строки YAML, где возникла ошибка:
1 2 3 4 5 6 7
use Symfony\Component\Yaml\Exception\ParseException;
try {
$value = Yaml::parse('...');
} catch (ParseException $exception) {
printf('Unable to parse the YAML string: %s', $exception->getMessage());
}
Чтение файлов YAML
Метод parseFile() анализирует содержание YAML в указанном файле и преобразует его в PHP значение:
1 2 3
use Symfony\Component\Yaml\Yaml;
$value = Yaml::parseFile('/path/to/file.yaml');
Если во время анализа возникает ошибка, парсер вызывает исключение ParseException
.
Запись YAML-файлов
Метод dump() преобразует любой PHP массив в его представление YAML:
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\Yaml\Yaml;
$array = [
'foo' => 'bar',
'bar' => ['foo' => 'bar', 'bar' => 'baz'],
];
$yaml = Yaml::dump($array);
file_put_contents('/path/to/file.yaml', $yaml);
Если ошибка возникает во время сброса, парсер вызывает исключение DumpException.
Расширенные и вставленные массивы
Формат YAML поддерживает два типа представления для массивов, расширенное и вставленное. По умолчанию, дампер использует расширенное представление:
1 2 3 4
foo: bar
bar:
foo: bar
bar: baz
Второй аргумент метода dump() настраивает уровень, на котором вывод переключается с расширенного представления на вставленное:
1
echo Yaml::dump($array, 1);
1 2
foo: bar
bar: { foo: bar, bar: baz }
1
echo Yaml::dump($array, 2);
1 2 3 4
foo: bar
bar:
foo: bar
bar: baz
Отступы
По умолчанию, компонент YAML использует 4 пробела для отступа. Это может поменять с помощью третьего аргумента таким образом:
1 2
// использует 8 пробелов для отступа
echo Yaml::dump($array, 2, 8);
1 2 3 4
foo: bar
bar:
foo: bar
bar: baz
Числовые литералы
Длинные числовые литералы, будь они целыми числами, float или шестнадцатиричными, известны своей плохой читаемостью в коде и файлах конфигурации. Поэтому файлы YAML позволяют добавлять нижние подчёркивания для улучшения их читаемости:
1 2 3 4 5
parameters:
credit_card_number: 1234_5678_9012_3456
long_number: 10_000_000_000
pi: 3.14159_26535_89793
hex_words: 0x_CAFE_F00D
Во время анализа содержания YAML, все символы _
удаляются из содержания
числовых литералов, поэтому лимита количества нижних подчёркиваний, которые
вы можете включать или то, как вы группируете содержание, не существует.
Продвинутое использование: флажки
Анализ объектов и сброс
Вы можете сбрасывать объекты, используя флаг DUMP_OBJECT
:
1 2 3 4 5
$object = new \stdClass();
$object->foo = 'bar';
$dumped = Yaml::dump($object, 2, 4, Yaml::DUMP_OBJECT);
// !php/object 'O:8:"stdClass":1:{s:5:"foo";s:7:"bar";}'
И анализировать их, используя флаг PARSE_OBJECT
:
1 2 3
$parsed = Yaml::parse($dumped, Yaml::PARSE_OBJECT);
var_dump(is_object($parsed)); // true
echo $parsed->foo; // bar
Компонент YAML использует метод PHP serialize()
для генерирования представления
строки объекта.
Danger
Сериализация объекта специфична для этой реализации, другие парсеры
PHP YAML скорее всего не узнают тег php/object
, а не-PHP реализации
точно не узнают - используйте с осторожностью!
Анализ и сброс объектов в виде карт
Вы можете сбрасывать объекты, как Yaml-карты, используя флаг DUMP_OBJECT_AS_MAP
:
1 2 3 4 5
$object = new \stdClass();
$object->foo = 'bar';
$dumped = Yaml::dump(['data' => $object], 2, 4, Yaml::DUMP_OBJECT_AS_MAP);
// $dumped = "data:\n foo: bar"
И анализировать их, используя флаг PARSE_OBJECT_FOR_MAP
:
1 2 3 4
$parsed = Yaml::parse($dumped, Yaml::PARSE_OBJECT_FOR_MAP);
var_dump(is_object($parsed)); // true
var_dump(is_object($parsed->data)); // true
echo $parsed->data->foo; // bar
Компонент YAML использует приведение PHP (array)
, чтобы сгенерировать строчное
представление объекта в виде карты.
Работа с невалидными типами
По умолчанию, парсер закодирует невалидные типы, как null
. Вы можете заставить
парсер вызывать исключения, используя флаг PARSE_EXCEPTION_ON_INVALID_TYPE
:
1 2
$yaml = '!php/object \'O:8:"stdClass":1:{s:5:"foo";s:7:"bar";}\'';
Yaml::parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); // throws an exception
Схожим образом вы можете использовать DUMP_EXCEPTION_ON_INVALID_TYPE
при дампе:
1 2
$data = new \stdClass(); // by default objects are invalid.
Yaml::dump($data, 2, 4, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE); // throws an exception
Работа с датами
По умолчанию, парсер YAML преобразует строки без кавычек, которые будут
выглядеть как дата или дата-время во временную метку Unix; например, 2016-05-27
или 2016-05-27T02:59:43.1Z
(ISO-8601):
1
Yaml::parse('2016-05-27'); // 1464307200
Вы можете заставить его преобразовывать в экземпляр DateTime
, используя флаг
PARSE_DATETIME
:
1 2
$date = Yaml::parse('2016-05-27', Yaml::PARSE_DATETIME);
var_dump(get_class($date)); // DateTime
Сброс многострочных блоков литералов
В YAML многострочные строки могут быть представлены, как блоки литералов. По умолчанию, дампер закодирует много строк в виде инлайновой строки:
1 2 3
$string = ["string" => "Multiple\nLine\nString"];
$yaml = Yaml::dump($string);
echo $yaml; // string: "Multiple\nLine\nString"
Вы можете заставить его использовать блок литералов с помощью флага
DUMP_MULTI_LINE_LITERAL_BLOCK
:
1 2 3 4 5 6 7
$string = ["string" => "Multiple\nLine\nString"];
$yaml = Yaml::dump($string, 2, 4, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
echo $yaml;
// string: |
// Multiple
// Line
// String
Анализ PHP-констант
По умолчанию, YAML-парсер относится к PHP константам, включенным в содержание,
как в обычным строкам. Используйте флаг PARSE_CONSTANT
и специальный синтаксис
!php/const
, чтобы проанализировать их, как соответствующие PHP константы:
1 2 3
$yaml = '{ foo: PHP_INT_SIZE, bar: !php/const PHP_INT_SIZE }';
$parameters = Yaml::parse($yaml, Yaml::PARSE_CONSTANT);
// $parameters = ['foo' => 'PHP_INT_SIZE', 'bar' => 8];
Анализ PHP-исчислений
Парсер YAML поддерживает PHP-исчисления, как модульные, так и бэк-энда. По
умолчанию, они анализируются как обычные строки. Используйте флаг PARSE_CONSTANT
и специальный синтаксис !php/enum
, чтобы анализировать их как реальные PHP-исчисления:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
enum FooEnum: string
{
case Foo = 'foo';
case Bar = 'bar';
}
// ...
$yaml = '{ foo: FooEnum::Foo, bar: !php/enum FooEnum::Foo }';
$parameters = Yaml::parse($yaml, Yaml::PARSE_CONSTANT);
// значение ключа 'foo' - это строка, так как она пропустила синтаксис `!php/enum`
// $parameters = ['foo' => 'FooEnum::Foo', 'bar' => FooEnum::Foo];
$yaml = '{ foo: FooEnum::Foo, bar: !php/enum FooEnum::Foo->value }';
$parameters = Yaml::parse($yaml, Yaml::PARSE_CONSTANT);
// значение ключа 'foo' - это строка, так как она пропустила синтаксис `!php/enum`
// $parameters = ['foo' => 'FooEnum::Foo', 'bar' => 'foo'];
Вы также можете использовать !php/enum
, чтобы получить все случаи исчислений,
указав только исчисление FQCN:
1 2 3 4 5 6 7 8 9 10 11
enum FooEnum: string
{
case Foo = 'foo';
case Bar = 'bar';
}
// ...
$yaml = '{ bar: !php/enum FooEnum }';
$parameters = Yaml::parse($yaml, Yaml::PARSE_CONSTANT);
// $parameters = ['bar' => ['foo', 'bar']];
7.1
Поддержка использования исчисления FQCN без указания регистра
была введена в Symfony 7.1.
Анализ и сброс бинарных данных
Вы можете сбросить бинарные данные, используя флаг DUMP_BASE64_BINARY_DATA
:
1 2 3 4
$imageContents = file_get_contents(__DIR__.'/images/logo.png');
$dumped = Yaml::dump(['logo' => $imageContents], 2, 4, Yaml::DUMP_BASE64_BINARY_DATA);
// logo: !!binary iVBORw0KGgoAAAANSUhEUgAAA6oAAADqCAY...
Бинарные данные автоматичеки анализируются, если они включают в себя флаг YAML
!!binary
(нет необходимости передавать какой-либо флаг парсеру Yaml):
1 2 3
$dumped = 'logo: !!binary iVBORw0KGgoAAAANSUhEUgAAA6oAAADqCAY...';
$parsed = Yaml::parse($dumped);
$imageContents = $parsed['logo'];
Анализ и сброс пользовательских тегов
Кроме встроенной поддержки тегов вроде !php/const
и !!binary
, вы можете
определить ваши собственные YAML теги и анализировать их с помощью флага PARSE_CUSTOM_TAGS
:
1 2 3 4 5
$data = "!my_tag { foo: bar }";
$parsed = Yaml::parse($data, Yaml::PARSE_CUSTOM_TAGS);
// $parsed = Symfony\Component\Yaml\Tag\TaggedValue('my_tag', ['foo' => 'bar']);
$tagName = $parsed->getTag(); // $tagName = 'my_tag'
$tagValue = $parsed->getValue(); // $tagValue = ['foo' => 'bar']
Если содержание для сброса содержит объекты TaggedValue, то они автоматически преобразуются в YAML теги:
1 2 3 4 5
use Symfony\Component\Yaml\Tag\TaggedValue;
$data = new TaggedValue('my_tag', ['foo' => 'bar']);
$dumped = Yaml::dump($data);
// $dumped = '!my_tag { foo: bar }'
Сброс Null-значений
Официальная спецификация YAML использует и null
, и ~
для представления значения null.
Этот компонент использует по умолчанию null
при сбросе значений null, но
вы можете сбрасывать их как ~
с флагом DUMP_NULL_AS_TILDE
:
1 2 3 4 5
$dumped = Yaml::dump(['foo' => null]);
// foo: null
$dumped = Yaml::dump(['foo' => null], 2, 4, Yaml::DUMP_NULL_AS_TILDE);
// foo: ~
Сброс числовых ключей как строк
По умолчанию
По умолчанию ключи массива, состоящего только из цифр, передаются в виде целых чисел.
Для того чтобы сбрасывать только строковые ключи, вы можете использовать флажок
DUMP_NUMERIC_KEY_AS_STRING
:
1 2 3 4 5
$dumped = Yaml::dump([200 => 'foo']);
// 200: foo
$dumped = Yaml::dump([200 => 'foo'], 2, 4, Yaml::DUMP_NUMERIC_KEY_AS_STRING);
// '200': foo
Валидация синтаксиса
Синтаксис содержания YAML может быть валидирован через CLI, используя команду LintCommand.
Для начала, установите компонент Console:
1
$ composer require symfony/console
Создайте консольное приложение с lint:yaml
в качестве его единственной команды:
1 2 3 4 5 6 7 8 9
// lint.php
use Symfony\Component\Console\Application;
use Symfony\Component\Yaml\Command\LintCommand;
(new Application('yaml/lint'))
->add(new LintCommand())
->getApplication()
->setDefaultCommand('lint:yaml', true)
->run();
Далее, выполните скрипт для валидации содержания:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# валидирует один файл
$ php lint.php path/to/file.yaml
# или валидирует несколько файлов
$ php lint.php path/to/file1.yaml path/to/file2.yaml
# или все файлы в каталоге
$ php lint.php path/to/directory
# или все файлы в нескольких каталогах
$ php lint.php path/to/directory1 path/to/directory2
# или содержание, переданное STDIN
$ cat path/to/file.yaml | php lint.php
# вы также можете исключить один или более файлов из проверки
$ php lint.php path/to/directory --exclude=path/to/directory/foo.yaml --exclude=path/to/directory/bar.yaml
Результат записывается в STDOUT и использует формат простого текста по
умолчанию. Добавьте опцию --format
, чтобы получить вывод в формате JSON:
1
$ php lint.php path/to/file.yaml --format json
Tip
Команда проверки соблюдения стандартов кода также сообщит обо всех устареваниях в провеяемых YAML файлах. Это может быть, к примеру, быть полезным для определения устареваний содержания YAML файлов во время автоматизированных тестов.