YAML парсер на Symfony framework

от автора

Привет, Хабр! Сегодня я расскажу вам о том, как использовать YAML‑парсер в Symfony.

YAML — это человекочитаемый формат сериализации данных, который используется для конфигурационных файлов. И в Symfony для этого есть компонент Yaml, который позволяет парсить YAML‑строки и файлы в PHP‑значения и обратно.

Компонент Yaml состоит из двух основных классов:

  1. Parser: парсит YAML‑строки и файлы в PHP‑значения.

  2. Dumper: преобразует PHP‑значения обратно в YAML‑строки.

Для упрощения есть фасадный класс Yaml, который имеет статические методы для наиболее распространенных операций.

Чтение YAML-строк и файлов

Чтобы распарсить YAML‑строку, есть метод Yaml::parse():

use Symfony\Component\Yaml\Yaml;  $yamlString = " foo: bar baz:   - qux   - quux ";  $data = Yaml::parse($yamlString);  // $data будет содержать: // [ //     'foo' => 'bar', //     'baz' => ['qux', 'quux'], // ] 

Для чтения YAML из файла метод Yaml::parseFile():

use Symfony\Component\Yaml\Yaml;  $data = Yaml::parseFile('/path/to/file.yaml');

Если в процессе парсинга произойдет ошибка, будет выброшено исключение ParseException. Лучше обрабатывать это исключение, чтобы получать информацию об ошибке:

use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Yaml;  try {     $data = Yaml::parseFile('/path/to/file.yaml'); } catch (ParseException $exception) {     printf('Не удалось распарсить YAML: %s', $exception->getMessage()); }

Чтобы преобразовать PHP‑значение в YAML‑строку, используйте метод Yaml::dump():

use Symfony\Component\Yaml\Yaml;  $data = [     'foo' => 'bar',     'baz' => ['qux', 'quux'], ];  $yamlString = Yaml::dump($data);  // $yamlString будет содержать: // foo: bar // baz: //     - qux //     - quux

Можно настроить уровень вложенности, при котором массивы будут инлайнены, передав второй аргумент в метод dump():

$yamlString = Yaml::dump($data, 1);  // $yamlString будет содержать: // foo: bar // baz: [qux, quux]

Yaml поддерживает сериализацию и десериализацию объектов. Для этого при дампе данных необходимо использовать флаг Yaml::DUMP_OBJECT:

use Symfony\Component\Yaml\Yaml;  $object = new \stdClass(); $object->foo = 'bar';  $yamlString = Yaml::dump($object, 2, 4, Yaml::DUMP_OBJECT);  // $yamlString будет содержать: // !php/object 'O:8:"stdClass":1:{s:3:"foo";s:3:"bar";}'

При парсинге такого YAML необходимо использовать флаг Yaml::PARSE_OBJECT:

use Symfony\Component\Yaml\Yaml;  $yamlString = "!php/object 'O:8:\"stdClass\":1:{s:3:\"foo\";s:3:\"bar\";}'";  $data = Yaml::parse($yamlString, Yaml::PARSE_OBJECT);  // $data будет объектом stdClass с свойством foo, равным 'bar'

Также YAML поддерживает различные типы данных, такие как даты, булевы значения и т. д. Компонент Yaml автоматом преобразует их в соответствующие PHP‑значения:

is_active: true created_at: 2025-02-08
use Symfony\Component\Yaml\Yaml;  $yamlString = " is_active: true created_at: 2025-02-08 ";  $data = Yaml::parse($yamlString);  // $data будет содержать: // [ //     'is_active' => true, //     'created_at' => new \DateTime('2025-02-08'), // ]

Помимо этого, можно использовать пользовательские теги для обозначения специальных типов данных. Компонент Yaml позволяет работать с такими тегами с помощью класса TaggedValue:

custom_tag: !mytag   foo: bar
use Symfony\Component\Yaml\Tag\TaggedValue; use Symfony\Component\Yaml\Yaml;  $yamlString = " custom_tag: !mytag   foo: bar ";  $data = Yaml::parse($yamlString, Yaml::PARSE_CUSTOM_TAGS);  // $data будет содержать: // [ //     'custom_tag' => new TaggedValue('mytag', ['foo' => 'bar']), // ]

Пример использования YAML-парсера

Представим, что у нас есть YAML‑файл, описывающий конфигурацию приложения с различными средами (development, testing, production), настройками базы данных, кэша и сервисов:

environments:   development:     debug: true     database:       host: localhost       port: 3306       name: dev_db       user: dev_user       password: dev_pass     cache:       enabled: false   testing:     debug: true     database:       host: localhost       port: 3306       name: test_db       user: test_user       password: test_pass     cache:       enabled: true       type: memory   production:     debug: false     database:       host: db.prod.example.com       port: 3306       name: prod_db       user: prod_user       password: prod_pass     cache:       enabled: true       type: redis       host: cache.prod.example.com       port: 6379 services:   email:     provider: smtp     host: smtp.example.com     port: 587     username: no-reply@example.com     password: email_pass   payment:     provider: stripe     api_key: sk_live_12345 

Задача: написать скрипт на PHP, который будет читать этот файл и выводить настройки для указанной среды.

require 'vendor/autoload.php';  use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Exception\ParseException;  function getConfigForEnvironment($env) {     try {         $config = Yaml::parseFile('app_config.yaml');     } catch (ParseException $e) {         printf('Не удалось разобрать YAML: %s', $e->getMessage());         return null;     }      if (!isset($config['environments'][$env])) {         echo "Среда '$env' не найдена в конфигурации." . PHP_EOL;         return null;     }      $envConfig = $config['environments'][$env];     $servicesConfig = $config['services'];      return [         'environment' => $envConfig,         'services' => $servicesConfig     ]; }  // Пример использования $environment = 'production'; $config = getConfigForEnvironment($environment);  if ($config) {     echo "Настройки для среды '$environment':" . PHP_EOL;     print_r($config['environment']);      echo "Настройки сервисов:" . PHP_EOL;     print_r($config['services']); } 

Вывод:

Настройки для среды 'production': Array (     [debug] =>      [database] => Array         (             [host] => db.prod.example.com             [port] => 3306             [name] => prod_db             [user] => prod_user             [password] => prod_pass         )      [cache] => Array         (             [enabled] => 1             [type] => redis             [host] => cache.prod.example.com             [port] => 6379         )  ) Настройки сервисов: Array (     [email] => Array         (             [provider] => smtp             [host] => smtp.example.com             [port] => 587             [username] => no-reply@example.com             [password] => email_pass         )      [payment] => Array         (             [provider] => stripe             [api_key] => sk_live_12345         )  )

Ограничения

Компонент Yaml не поддерживает некоторые возможности YAML 1.2, такие как:

  • Многостраничные документы (--- и ... маркеры);

  • Комплексные ключи в маппингах;

  • Некоторые теги и типы (!!set, !!omap, !!pairs и т. д.).


В заключение хочу напомнить про открытый урок, который пройдёт в Otus 13 февраля — «Генерируем API-клиент без помощи ChatGPT». На нём вы научитесь генерировать API-клиент на базе спецификации Open API и использовать его в своих приложениях. Записаться можно на странице курса «Symfony Framework».


ссылка на оригинал статьи https://habr.com/ru/articles/880762/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *