Одни и те же данные нужно представить в разном виде. В коде удобно работать с высокоуровневыми моделями. Но для сохранения этих данных в базу данных, как правило, данные требуется перевести в более простой вид, обычно в ассоциативный массив. Для передачи данных между приложениями используют простые DTO сущности.
Компонент позволяет легко конвертировать ваши данные в ассоциативный массив из модели и обратно заполнять вашу модель данными.
Задача класса Extractor извлечь из вашей модели данные согласно указанынм правилам.
$extractor = new Extractor;
$normalizer = new \PTS\Hydrator\Normalizer;
$model = new Model([
'id' => 1,
'name' => 'Alex'
'email' => 'some@web.dev'
]);
$rules = [
'id' => [], // prop as dto`s key
'name' => [
'prop' => 'name', // prop is name field in model
],
'email' => [
'get' => 'getEmail', // getter $model->getEmail();
]
];
$rules = $normalizer->normalize($rules);
$extractor->extract($model, $rules)
Правила извлечения данных описываются в виде ассоциативного массива, где ключ массива это имя ключа в DTO сущности. Наприимер поле модели name можно замапить в поле с именем login в DTO сущности таким образом.
$rules = [
'login' => [
'prop' => 'name',
],
...
];
$extractor->extract($model, $rules);
Извлечение через prop позволяет извлеч из модели поле с любой областью видимости (public/protect/private). Если значение prop не указано явно, то оно равно имени ключа DTO сущности. В следующем примере это будет значение name.
$rules = [
'name' => [],
...
];
$rules = $normalizer->normalize($rules);
$extractor->extract($model, $rules)
Помимо извлечения данных свойств из модели, данные можно получить через вызов метода модели (getter).
$rules = [
'name' => [
'get' => 'getName', // getter $model->getName();
],
];
$extractor->extract($model, $rules);
Геттер имеит более высокий приоритет, чем свойтво prop.
Класс Hydrator позволяет наполнить модель данными.
$hydrator = new Hydrator;
$dto = [
'id' => 1,
'login' => 'Alex'
'email' => 'some@web.dev
];
$rules = [
'id' => [], // prop as dto`s key
'login' => [
'prop' => 'name', // dto key login fill property name
],
'email' => [
'set' => 'setEmail', // setter $model->setEmail();
]
];
$rules = $normalizer->normalize($rules);
$model = $hydrator->hydrate($dto, Model::class, $rules);
$model2 = new Model;
$hydrator->hydrateModel($dto, $model2, $rules);
Правила гидрации точно такие же как и у extractor сущности.
Класс HydratorService является совмещает в себе Hydrator и Extractor. Также он требует правил в виде сущности Rules, которая сглаживает правил и позволяет описывать их более лаконично
$hydratorService = new HydratorService;
$rules = [
'id' => [], // prop as dto`s key
'login' => [
'prop' => 'name', // dto key login fill property name
],
'email' => [
'set' => 'setEmail', // setter $model->setEmail();
]
];
$rules = $normalizer->normalize($rules);
$dto = $hydratorService->extract($model, $rules);
$model = $hydratorService->hydrate($dto, Model::class, $rules);
Если требуется рекурсивная гидрация/извлечение зависимостей, требуется декларативно объявлять правила трансформации, вызывать pipe функции для фильтрации значения, то стоит воспользоваться надсткойкой над этой билбиотекой - https://github.com/alexpts/php-data-transformer2