Привет, Хабр! Сегодня я расскажу вам о том, как использовать YAML‑парсер в Symfony.
YAML — это человекочитаемый формат сериализации данных, который используется для конфигурационных файлов. И в Symfony для этого есть компонент Yaml
, который позволяет парсить YAML‑строки и файлы в PHP‑значения и обратно.
Компонент Yaml
состоит из двух основных классов:
Parser: парсит YAML‑строки и файлы в PHP‑значения.
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".
DarkHost
Спасибо за статью