Компонент Yaml

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

Компонент Yaml

Компонент Yaml завантажує та скидає файли YAML.

Що це?

Компонент Symfony Yaml парсить YAML рядки, щоб перетворити їх на PHP-масиви. Він також може перетворити PHP-масиви на рядки YAML.

YAML, YAML не є мовою розмітки - це дружній стандарт серіалізації даних для всіх мов програмування. YAML є чудовим форматом для ваших файлів конфігурації. Файли YAML настільки ж експресивні, як і файли XML, і настільки ж читані, як файли INI.

Компонент Symfony Yaml реалізує обраний піданбір функцій, визначених у специфікації версії YAML 1.2.

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('Неможливо парсувати рядок YAML: %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

Числові літерали

Довгі числолві літерали, цілі числа, плаваючі чи шістнадцяткові, відомі своєю поганою читаністю в коді та файлах конфігурації. Тому файли 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() для генерування представлення рядку обʼєкта.

Caution

Серіалізація обʼєкта специфічна в цій реаізації, інші парсери 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); // викликає виключення

Робота з датою

За замовчуванням, парсер 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; // рядок: "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'];

6.2

Підтримка PHP-зчислень була представлена в Symfony 6.2.

Парсинг та скидання бінарних даних

Ви можете скинути бінарні дані, використовуючи прапорець 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: ~

Валідація синтаксису

Синтаксис змісту 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-файлів під час автоматизованих тестів.