И всё-таки, как «правильно» выполнять из PHP сложные sql-запросы?

Года три назад попросили меня написать простенькую софтинку на PHP для печати счетов. Так уж получилось, что логика СУБД (MSSQL), на которую опиралась эта софтина, была весьма монструозна — около восьмиста таблиц, перепутанных взаимными связями. Поэтому большинство запросов включали в себя условные вызовы аггрегирующих функций (самое простое — sum(when eq then a else 0 end)), PIVOT\UNPIVOT и тому подобное.

C учетом моего не слишком уж большого опыта на тот момент я решил не ввязываться в data mapping\active record и просто закинул запросы в текстовые файлы, сделал в них текстовые плейсхолдеры типа {PARAM1} и написал функцию, заменяющую текст плейсхолдера на значения переменных из ассоциативного массива.

С тех пор прошло много времени — софтинка обзавелась аджаксовой мордочкой, мигрировала на мой любимый CI, обзавелась двумя десятками модулей, содержащих всякую аналитику. Неизменным оставался лишь способ вызова SQL-запросов — ассоциативный массив, текстовый файл, плейсхолдеры.

И, что удивительно, всё это безобразие работает и по сей день. Правда, количество костылей и подпорок уже начинает слегка раздражать.
А именно — ручной escaping, type-checking, в конце концов — не работает ctrl+пробел. Я уж промолчу про то, что отладка запросов нормально не работает из-за «неродных» плейсхолдеров, и syntax check в PhpStorm из-за этого сходит с ума. А вместе с ним и я, потихоньку.

Doctrine на такой сложности запросов превращает двухстрочный вызов в нечто невероятное, а про размер схемы я просто тактично умолчу. Родные плейсхолдеры (:PARAM) не умеют содержать в себе куски запроса. А у нас автогенерация во все поля, кастомные фильтры, отключаемые джойны из внешних СУБД, находящихся за 4-5 тыс км от нашей серверной комнаты. Паника, боль, унижение.

В общем, родился план. Делаем класс Query с тайп-чекингом, возвратом результатов в XML (да, есть и такое) либо в массиве. Дальше делаем кучу наследников для каждого отдельного SQL-запроса, у которых в public -секции висит класс с перечисленными входными параметрами. А дальше всё так же — текстовый файл и плейсхолдеры.

Обратно — либо массивом, либо XML, либо неким классом наподобие ResultSet->First (next,last).

Всё это до боли напоминает изобретение велосипеда. Подозреваю, что всё это уже написано до нас. Но беглый гуглеж не помог. Может, кто сталкивался с такими вещами?
  • Вопрос задан
  • 5320 просмотров
Пригласить эксперта
Ответы на вопрос 3
@rPman
Не нужно перебарщивать, решите только одну главную проблему передачи параметров — escaping и quoting параметров, никаких монструозных велосипедов, только поправьте метод выполняющий ваши запросы, :param пусть идут в sql-запрос без изменений (а сам запрос сделать параметризованным, список параметров получается просто поиском всех вхождений /\:(\w+)/), а {param} заменяются по старинке, пусть там останутся куски самого запроса с выражениями.
Ответ написан
OnYourLips
@OnYourLips
DBAL от доктрины использую.
Выглядит как-то некачественно, но ничего лучше не видел.

возвратом результатов в XML
Зачем?
Ответ написан
@yar229
Я, наверное, чего-то не понял, но вроде же говорится о функционале хранимых процедур

create procedure BigBadQueryWithParams(@p1 int, @p2 nvarchar(1024))
as
begin
select * from MyTable where Field1 = @p1;
end;


mssql_init, mssql_bind параметры и mssql_execute...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
DELOGRAM Москва
от 100 000 до 180 000 руб.
Hunt4You Севастополь
от 60 000 до 120 000 руб.