TGViewer
Хэндлим тему | Дерепко Хэндлим тему | Дерепко @handle_topic · 275 subscribers
Post #30 551
Remap – гидрация результатов sql запросов с преобразованием
#пост

Довольно часто мне приходилось делать raw sql запросы в БД для получения данных. Причин тому было несколько:

- Так быстрее
- Не нужно писать длинные билдеры
- Запрос часто менялся, проще всего переносить as-is из требований в код
- Подсветка синтаксиса в IDE
- Удобная отладка: скопировал в DB Viewer и запускаешь
- И многое другое

Зачастую в проекте уже была какая-нибудь ORM или Active Record, где всегда результат запроса был объектом с необходимыми свойствами и типами.

Однако работа с raw sql обычно заканчивалась перегоном массивом из одного метода в другой.

Это неудобно:

- Нет типизации параметров функции – array $data
- Нет типизации свойств – $data['user_id'] – int/string?
- Нет понятия наличия свойства в массиве вообще – $data['unknown_prop'] – ошибка, которую найдешь только при выполнении кода

Как-то давно общаясь в чате про Active Record в Yii3 ко мне пришло озарение, что AR – это всё еще сложно – нужно наследоваться от базового класса или подключать trait, где-то доставать фабрики и самое главное, всё равно raw sql не смапить в модельку.

К тому моменту hydrator из Yii3 был почти готов и я решил сделать Proof Of Concept обычного data-mapper, с использовать db и hydrator.

Вот что из этого вышло:

Remap

Библиотека содержит лишь 1 класс и делегирует работу по исполнению запроса в yiisoft/db. Создание объекта и его наполнение библиотека делегирует в yiisoft/hydrator.

Таким образом, логика выглядит линейной и понятной:

1. Выполняет raw sql запрос
2. Проходим построчно по результату запроса
3. Создаем DTO и наполняем его нужными полями

Всё это скрыто в методе Remap::map()

Пример работы с библиотекой:



final class Todo
{
public int $id;
public string $title;
public int $status;
public int $created_at;
}

$sql = 'SELECT id, title, status, created_at FROM todo WHERE id = :id LIMIT 1';
$params = ['id' => 1];

$remap->map(Todo::class, $sql, $params);


Remap::map()

Метод принимает первым аргументов класс, который нужно будет создать и наполнить.

Второй и третий аргументы – сам запрос и параметры для подстановки. Можно передать во второй параметр string $sql , а в третий array $params , а можно сразу во второй передать [$sql, $params]

Метод возвращает \Generator объектов. Это позволит обрабатывать большие объемы результатов запроса и не падать с нехваткой памяти.

Как вариант использования библиотеки я сразу подметил, что удобно было бы использовать класс, как AR и Query Builder, поэтому с легкостью вышеупомянутый пример можно превратить в следующее:


$remap->map(Todo::class, Todo::selectOne($id));
$remap->map(Todo::class, Todo::selectAll());


Использовать можно по-разному, поэтому для еще большего упрощения записи можно написать следующее:


$remap->map(...Todo::selectAll());


Статические методы в Todo в текущих примерах будут возвращать массив из нужных значений:

- [$sql, $params] в первом примере
- [self::class, $sql, $params] во втором примере

А использование yiisoft/hydrator позволило использовать Attributes для произведения дополнительных трансформаций. Например:


final class TodoModelHydrator
{
#[Data('id')] // В свойство $identifier запишется то, что лежит в id свойстве
public string $identifier; // дополнительно cast from int -> to string
#[Data('title')] // title -> text
public string $text;
public string $status; // int -> string
#[Data('created_at')] // created_at -> date_created
public string $date_created; // int -> string
}


Таким образом, результат запроса можно преобразовать под нужные конвенции объектов и не зависеть от устройства внешнего хранилища.

Причесал библиотеку, написал тесты, подкрутил Psalm на 1 уровень, тегнул 1.0.

Надеюсь эта библиотека поможет и вам. Буду рад любым предложениям по улучшению.

——

Полезные ссылки:

Remap
Использование атрибутов yiisoft/hydrator

@handle_topic
GitHub GitHub - xepozz/remap: The library allows you to map data from the database to objects. The library allows you to map data from the database to objects. - xepozz/remap
  • 👍 11
  • 🔥 7
More from @handle_topic
  1. Sep 9, 2026Пыхник’26 — целая неделя PHP! С 28 сентября по 2 октября пройдёт Пыхник’26 — онлайн-конфер…
  2. Aug 24, 2026Мой Pull Request в vlucas/dotenv смёржили! Рад ли я? Конечно. Прихнаюсь честно, у меня это…
  3. Aug 5, 2026Jetbrains выделили LSP ядро для Java/Kotlin, так что теперь вся (а вся?) мощщщщь IDEA дост…
  4. Jul 30, 2026Вайбкодеры?
  5. Jul 19, 2026Когда выучил высоконагруженные системы @git_rebase / send memes
  6. Jun 30, 2026Jetbrains Air на Windows! Если вы вдруг разрабатываете на винде (сожалею вам), то можете п…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →