Разбор оператора запроса MySQLi для получения параметров для миграции PDO - PullRequest
1 голос
/ 22 июня 2019

Этот вопрос касается синтаксического анализа в PHP, а не о том, как перенести MySQLi в PDO.

Я хочу перенести старый код из MySQLi в PDO.На сайте более 400 строк запросов.Я хочу пересмотреть код для использования подготовленных операторов.

Т.е. преобразовать

$query = 'SELECT * from table where x='.$x.' and y > '.$y.' or (z<= 35 and auth like "%ed")'
$result = $conn->query($query);

в

$query = 'SELECT * from table where x = ? and y > ? or (z <= ? and auth like ?)';
$stmt = $conn->prepare($query);
$stmt->bind_param($x, $y, $35, '%ed');
$stmt->execute();

Я начал с анализа строки запроса $, чтобы найти«где», затем поиск «и» для разделения пар параметр / значение и т. д.

Редактировать : это базовый код для чтения строк в файле (в данном случае, a.php file):

$fn = fopen("myfile.php","r+");
while(!feof($fn))  {
    $line = fgets($fn);
    if (strpos($line, 'select'){
       // add parse code here
    };
}

при поиске строки с оператором запроса строка будет буквальной строкой, наподобие этой:

($ line =) $ query ='выберите * в меню, где authlvl> 0 и authlvl <='.$ authlvl.'order by title'; </p>

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

$where = substr($line, strpos($line, 'where') + 5);
$pair = array();
$j = 0;
$st = 0;
if (strpos(substr($where, $st), 'and', $st)) > 0){
    while (($and = strpos(substr($where, $st), 'and', $st)) > 0){
        $pair[$j] = trim(substr($where, $st, $and - 1));
        $pair[$j+1] = trim(substr($where, $and + 4));
        $st = $and;
        $j++;
    }
}
$ops = array(' ', '<', '>', '=');
(find operators to identify parameters and values for each pair...)

Это интуитивно неэффективно.Есть ли лучший способ разобрать строку запроса $, чтобы найти параметры, чем этот?Обратите внимание, что в строке может быть «order by» и т. Д., Которые должны просто добавляться после нахождения параметров.

1 Ответ

0 голосов
/ 28 июня 2019

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

Чтение строки в файле PHP с помощью fgets () дает строку (включая имя переменной и весь синтаксис), например:

$query = 'select * from menu where authlvl>0 and authlvl<=' . $authlvl . ' order by title';

Первый шаг - подтвердить, что строка кода содержит инструкцию SELECT с предложением WHERE и не является комментарием. Предложение WHERE извлекается и разделяется на и / или для получения условных пар параметр / значение.

Затем пары параметр / значение можно разделить, чтобы можно было переписать оператор в соответствии с PDO.

if (preg_match('/(=\s*\'select|=\s*"select)/', $line) && preg_match('/(where)/i', $qry) && !preg_match('/^(\s*\/\/)/', $line)) {
    $z = preg_match('/(?<=where).+/i', $qry, $matches);
    $where = trim($matches[0]);
    $pairs = preg_split('/( and | or )/', $where);
    $andor = preg_match_all('/(\s*and\s*|\s*or\s*)+/', $where, $ao);

Условные пары разбиваются путем нахождения операторов сравнения в каждой паре.

preg_match('/.+?(?:[\=<>]+)/', $pair, $par)
preg_match('/[^(' . preg_quote($par[0]) . ')].*/', $pair, $val)

Значения могут быть заменены знаками вопроса, а оператор запроса переписан. Значения также могут быть помещены в массив для PDO.

$query = 'select * from menu where authlvl > ? and authlvl <= ? order by title';
$values = array('0', $authlvl);
$stmt = $this->pdosc->prepare($query);
$stmt->execute($values);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

Мне удалось использовать регулярные выражения для захвата практически любых вариаций операторов SELECT, которые у меня есть, и быстрого обновления (переноса) моих файлов из MySQLi в PDO. Конечно, у меня есть функция-обертка, которая принимает либо простую строку для оператора запроса (MySQLi), либо массив из 2 частей с запросом и значениями (PDO).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...