Эволюция DBAPI
Agel NashВ новых версиях MODX Evolution ожидается существенная переделка ядра. Ключевым улучшением станет полноценное внедрение паттерна Dependency Injection. Ну, а как этим пользоваться, я покажу на примере DBAPI. Но для начала расскажу с чего все начиналось, чтобы было понятно зачем…
Начало
Один из двух самых значимых классов для MODX Evolution это DBAPI. Для тех, кто в танке, этот класс нужен для работы с базой данных. Так вот, этот самый класс DBAPI немного хардкорного синтаксического сахара для mysqli. В нем определены методы, как select/update/insert/save/delete/etc… Видя подобные названия знающие люди сразу начинают думать в сторону ORM или ActiveRecord. Но не тут то было. Эти методы не имеют ничего общего с вышеназванными паттернами. Более того, методы работают с параметрами насколько по разному, что зачастую не совсем понятно какой же в итоге SQL запрос получится.
Давайте на примере
->select('id', 'site_content', array('id > 10', 'pagetitle = "test"')); //SELECT id FROM site_content WHERE id > 10 pagetitle = "test"
По логике, тут не хватает AND. Но нет, параметр where делает просто implode массива с пробелом. Хорошо. Запомнили. Смотрим следующий метод — update
->update(array('pagetitle' => 'new'), 'site_content', array('id > 10', 'AND pagetitle = "test"'));
А тут уже нельзя использовать массив в аргументе where. НО! У нас есть метод save который так же может принимать параметр where и пробрасывать его в select запрос или update в зависимости от результатов.
->save(array('pagetitle' => 'new'), 'site_content', array('id > 10', 'AND pagetitle = "test"'));
Если в базе не окажется документов с ID > 10 и pagetitle = «test», то будет вызван метод insert и как следствие, добавится новая запись у которой pagetitle будет установлен в значение new. В противном случае мы получим ошибку
trim() expects parameter 1 to be string, array given in
Помимо этого мы имеем кучу старевшего кода, в стиле _getFromStringFromArray, который ничем не отличается от
implode(' ', $tables)
Эксперимент
Исходя из вышеперечисленного захотелось попробовать немного причесать код и проверить — получился ли в результате сохранить обратную совместимость. Я взял класс DBAPIразрезал на части. После чего привел вызовы к единому стилю и тут стало очевидно, что завязка на mysqli не такая уж и жесткая. А это значит, что мы можем теоретически использовать pdo драйвер и скрестить MODX с любой базой данных.
Так, получилось самодостаточное решение, которое идеально подойдет для тех, кто не умеет работать с базой вне MODX. Покрыв код тестами почти на 90% пришла в голову мысль не изобретать велосипед, а прокинуть Illuminate\Database от Laravel в качестве альтернативы для mysqli драйвера. Вы не поверите, но получилось добиться почти полной совместимости (за исключением метода dataSeek, но ни в ядре, ни в компонентах этот метод не используется).
Что получилось
— Полная совместимость пакета со стандартным DBAPI классом
— Возможность использовать привычный синтаксис DBAPI вне MODX
— Поддержка полноценной ORM Eloquent для плавного переноса сайта на Laravel. Либо, как альтернатива поделке MODxAPI, которая входит в состав DocLister
Автор
Telegram: @agel_nash
Email: modx@agel-nash.ru