SQL-запрос на PHP (Версия 0.2) -7


Разработка веб-сайтов*, SQL*, PHP*

image

Внес изменения в свою реализацию класса для генерации SQL запросов по сравнению с прошлой версией. Однако прежде чем писать о них, хотелось сразу прояснить некоторые вопросы которые в первом посте остались, на мой взгляд, не раскрыты:

  1. Это не очередной QueryBuilder. Хотя синтаксис и выглядит похоже, но по сути работает это по-другому. QueryBuilder обычно выполняется в Runtime. Мой же код предварительно нужно компилировать и на выполнение запускать уже откомпилированную версию. В частности код с картинки будет скомпилирован в следующий код PHP:

    if (!isset($__query58)) {
        $__query58 = new \ML\SQL\Query(
             '0cfd84f430c39bb567ef7cd28bf36054', 
             array(
                      'server' => '***', 
                      'database' => '***', 
                      'user' => '***', 
                      'pass' => '***', 
                      'prefix' => 'ms-', 
                      'codepage' => 'utf8'
              )
        );
    }
    $__query58->sql = ' SELECT `profile`.`iduser` AS `profile.iduser`,`user`.`name` AS `user.name` FROM `ms-Users-Profile` AS `profile`LEFT OUTER JOIN `ms-Users-User` AS `user` ON `user`.`id`=`profile`.`iduser` WHERE (`profile`.`net`=\'VK\' OR `profile`.`net`=\'OK\') AND `user`.`sex`=\'M\'';
    $rows = $__query58->rows();

    При использовании переменных в качестве имен полей или значений они будут вставлены в запрос через вызовы специальных функций, которые исключат SQL-инъекцию.

  2. Для чего это нужно: я планирую сделать свой ORM (само собой с блекджеком и шлюхами) и PHPSQL будет являться абстрактным слоем для работы с БД. Планируется писать запросы в виде:

    select(id)->from(Users\User)->where(sex == 'M');

    Который затем будет компилировать в PHP код с промежуточной компиляцией в PHPSQL.

  3. Нет, такой подход с компиляцией файлов не будет тормозить работу. Достаточно сделать это один раз при первом обращении к файлу, а затем закешировать скомпилированный вариант и в дальнейшем работать уже с ним. Также это можно делать один раз при установке/обновлении движка через консоль. В этом случае нам вообще неважно сколько времени займет компиляция, главное чтобы итоговый файл работал быстро.

  4. Да, такой подход действительно может создавать проблемы в отладке. Потому что из-за сгенерированного кода при ошибке в коде номер строки ошибки будет соответствовать новому скомпилированному файлу, а не тому, в котором вы этот код набирали.На текущий момент я пока не придумал как это обойти. Если есть какие-то идеи — озвучьте их.

  5. Да, я в курсе что «вместо изобретения своего велосипеда лучше бы использовал что-то крутое, типа Doctrine|Eloquent|другой вариант». Но я пошел своим путем потому что 1) мне это интересно 2) мне это нравится.

  6. Почему не выложил на гибхаб: потому что данный класс использует функции из других моих библиотек, которые в свою очередь требуют еще библиотек и в общем это все занимает 17 мб исходных текстов, по которым нет справки. При этом из некоторых библиотек используется одна/две простенькие функции. На текущий момент пока не вижу смысла делать рефакторинг чтобы вынести этот функционал в отдельную небольшую папку для общего доступа. Будет интерес — выложу.

Ну а теперь перейдем к изменениям:

  • Самое основное нововведение — в новой редакции все константные строки интерпретируются как имена полей. Т.е. теперь вместо field(net) == 'VK' можно писать net == 'VK'. Для имен полей с символом тире в имени можно использовать оператор исполнения в обратных ковычках: `net-soc`== 'VK'. Функция field осталась, её можно использовать если имя поля, к примеру, находится в переменной: field($fieldname).

  • Исчезли функции вида _And, _Or. Теперь в условии нужно использовать вместо них операторы && и ||. Т.е. раньше было _Or(field(net)==value('VK'),field(net)==value('OK')), в новой редакции net=='VK' || net=='OK'

  • Добавилась поддержка JOIN запросов (на стартовой картинке как раз пример с ним).

  • Добавлен низкоуровневый метод Query, который позволяет создавать любые запросы,
    которые нельзя сделать с помощью специализированных функций. По сути это просто обычное формирование запроса с помощью конкатенации строк. Однако в методе можно использовать специальные функции, которые позволяют исключить SQL-инъекции.

  • Расширилась функция field. Теперь можно написать в виде field([<имя псевдонима таблицы>,]<имя поля>)[->as(<имя псевдонима поля>)]

  • Поддержка сортировки, группировки, условий агрегации

Для тех, кому интересно, тестовый полигон для компиляции кода находится по тому же адресу. Если найдете какую-то ошибку, пишите в комментариях. Пока это версия 0.2 так что ошибки весьма вероятны.

UPD: Судя по всему 90% комментаторов осилили только заголовок и картинку под ним и тут же начали писать комментарий в стиле «ваш велосипед гавно, лучше пишите на xxx/yyy/zzz». Хотя специально для таких был написан пункт 5.

UPD2: Добавил команды INSERT, UPDATE, DELETE. Также в команду SELECT добавил offset() и limit(). Так что теперь можно свою ORM делать.

UPD2.1: Добавил метод COUNT в SELECT. Если в нем указать переменную, то в неё вернется общее количество записей без учета команды LIMIT. Сам запрос тоже выполнится. Это для пагинаторов сделано.
-->


К сожалению, не доступен сервер mySQL