Php запрос к бд MySql

izula

Новичок
Добрый день )) Написал такой запрос к базе данных
$query = "select * from books where" . $searchtype . " like '%" . $searchterm . "%'";
При выполнении ругается
Fatal error: Uncaught mysqli_sql_exception: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'like '%Майкл Морган%'' at line 1 in C:\xampp\htdocs\results.php:31 Stack trace: #0 C:\xampp\htdocs\results.php(31): mysqli->query('select * from b...') #1 {main} thrown in C:\xampp\htdocs\results.php on line 31

'like '%Майкл Морган%'' Почему то одинарную кавычку воспринимает как двойную и выдает ошибку.
 

ksnk

прохожий
Ну, вообще-то у человека уже есть mysqli. Хотя он им не умеет пользоваться, ну да какие проблемы, будет не уметь пользоваться еще и PDO. Ну и с LIKE ни то ни другое толком работать не может все равно нужен полуручной ескейпинг.
 

AnrDaemon

Продвинутый новичок
Ну и с LIKE ни то ни другое толком работать не может все равно нужен полуручной ескейпинг.
Если вы не умеете его готовить, это не значит, что с ним нельзя нормально работать.
Да, действительно, при работе с LIKE нужно немного больше приседаний.
Но всё это можно описать тупо через SQL.
PHP:
/** Builds SQL snippet for substring comparison
 *
 * @param string $fieldName SQL field name.
 * @param int $args Number of values.
 * @param bool $caseless True for case-insensitive comparison.
 * @return string Constructed SQL snippet.
 */
function m_match_substring(string $fieldName, int $args, bool $caseless = false): string {
    if (empty($args)) {
        throw new \LogicException("No empty lists allowed in match", -1);
    }

    $template = $caseless
        ? "UPPER(%s) LIKE CONCAT('%%', UPPER(REPLACE(REPLACE(?, '\\\\', '\\\\\\\\'), '%%', '\\\\%%')), '%%') ESCAPE '\\\\'"
        : "%s LIKE CONCAT('%%', REPLACE(REPLACE(?, '\\\\', '\\\\\\\\'), '%%', '\\\\%%'), '%%') ESCAPE '\\\\'";
    return "(" . join(" OR ", array_fill(0, count($args), sprintf($template, m_quoteident($fieldName)))) . ")";
}
 

ksnk

прохожий
Интересно, слова "полуручной эскейпинг" и вот такая вот конструкция - это вот одно и то же или `это другое`?
Просто, чтобы напомнить, в начале речь шла о встроенных в систему средствах шаблонного sql- PDO или mysqli...

Ну и так, в качестве наблюдения, символ подчеркивания тоже неплохо бы эскейпить в лайке, к тому же эскейпить в like что-то обратным слешем - это генерировать такие вот монструозные склады обратных палок. Случайная утрата одной палки приведет к совершенно замечательным результатам. Обычно в таких случаях используется что-то менее радикальное, например +, синтаксис позволяет.
 

AnrDaemon

Продвинутый новичок

ksnk

прохожий
Покрывается тестированием.
Ну, раз о тестировании... Сколько нужно тестов, чтобы понять, что count от целого числа возвращает что-то не то. И сколько реально тестов было в опубликованном выше коде?

Код:
$x= "%s LIKE CONCAT('%%', REPLACE(REPLACE(?, '\\\\', '\\\\\\\\'), '%%', '\\\\%%'), '%%') ESCAPE '\\\\'";
$y= "%s LIKE CONCAT('%%', REPLACE(REPLACE(?, '+', '++'), '%%', '+%%')), '%%') ESCAPE '+'";
На вкус и цвет...
Хотя в этом случае я бы и от спринтфа отказался, чтобы еще проценты не дублировать и дополнительный гемор в читабельности избежать.
 
Сверху