MySQL подготовленный оператор возвращает 0 строк, без ошибок - PullRequest
0 голосов
/ 05 октября 2019

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

В этом конкретном случае я пытаюсь убедиться, что в базе данных существует ряд значений. Если они это сделают, верните истину. Если это не так, верните false.

Вот вспомогательная функция:

function verifyRow($a_verify) {
    //Pass $mysqli connection variable
    global $mysqli;

    //Create a string from the selection criteria
    $selection = implode(", ", (array) $a_verify->selection);

    //Transfer table contents to table variable just for consistency
    $table = $a_verify->table;

    //Create a string from the parameter types
    $type = implode("", (array) $a_verify->type);

    //Push a reference to the string of types to the parameter array
    $a_params[] =& $type;

    //For each result parameter, push a column = result string into the colvals array and create a reference to the parameter in the parameters array
    foreach ($a_verify->columns as $key => $value) {
        $a_colvals[] = "{$value} = ?";
        $a_params[] =& $a_verify->results->$key;
    }

    //Create a string from the column = result array
    $colvals = implode(" AND ", $a_colvals);

    //Generate a query
    $query = "SELECT {$selection} FROM {$table} WHERE {$colvals} LIMIT 1";

    //Prepare statement and error checking
    if (!($stmt = $mysqli->prepare($query))) {
        print "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
    }

    //Bind parameters and error checking
    if (!(call_user_func_array(array($stmt, 'bind_param'), $a_params))) {
        print "Binding parameters failed: (" . $mysqli->errno . ") " . $mysqli->error;
    }

    //Execute statement and error checking
    if (!$stmt->execute()) {
        print "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
    }

    //Get the result
    $result = $stmt->get_result();

    //Bind the result to a variable
    $row = $result->fetch_assoc();

    //If the row exists, return true
    if ($row) {
        return true;
    }
    //If the row doesn't exist, return false
    else {
        return false;
    }
}

Вот как я пытаюсь получить результат:

// Confirm there is a user in the db with this user code
$a_verify = (object) array(
    "selection" => (object) array(
        "*"
    ),
    "table" => "`users`",
    "columns" => (object) array(
        "`code`"
    ),
    "results" => (object) array(
        "'123456'"
    ),
    "type" => (object) array(
        "s"
    )
);
print verifyRow($a_verify); //Ideally 'true'

Вот как настроена база данных пользователей:

|-----|---------------|--------|
| id  |     email     |  code  |
--------------------------------
| 0   | test@test.com | 123456 |
--------------------------------

Есть идеи, в чем может быть проблема? Это сводит меня с ума.

1 Ответ

1 голос
/ 05 октября 2019

Вспомогательные функции великолепны, и здесь я полностью с вами. Но ... Вы называете этот ослепительный небоскреб кода "намного быстрее и проще", чем ванильный SQL на самом деле?

По какой-то причине вы постоянно перемещаете свой код назад и вперед от одногоформат в другой. Например, вы создаете массив array("*"), затем конвертируете его в объект (object) и затем ... конвертируете его обратно в массив (array) $a_verify->selection. Почему?

Или вы берете простой SQL-запрос SELECT * FROM users WHERE code = ? и создаете многострочную конструкцию, в которой ключевые слова SQL заменяются ключами массива с добавлением множества кавычек, скобок и прочего. А затем преобразовать его обратно в SQL .

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

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

Позвольте мне показать вам реальную вспомогательную функцию. Это делает ваш код коротким и читаемым, а также поддерживает все возможности SQL (например, упорядочивая результаты):

function prepared_query($mysqli, $sql, $params, $types = "")
{
    $types = $types ?: str_repeat("s", count($params));
    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    return $stmt;
}

Если вам интересно, как это работает, вы можете прочитать объяснение, которое я написал здесь .

Теперь давайте перепишем вашу вспомогательную функцию на основе моей

function verifyRow($mysqli, $sql, $parameters) {
    $result = prepared_query($mysqli, $sql, $parameters)->get_result();
    return (bool)$result->fetch_assoc();
}

Всего две строки кода!

А теперь, чтобы проверить фактическую строку:

var_dump(verifyRow($mysqli, "SELECT 1 FROM users WHERE code = ?", ['12345']));

Одна строка вместо дюжины.

Теперь вопрос, почему он ничего не находит. Есть две возможные причины.

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

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

error_reporting(E_ALL);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
ini_set('log_errors',1); // well to be 100% sure it will be logged

, чтобы убедиться, что все ошибки PHP и mysql появятся сами собой. Затем запустите код снова. Если это не приведет к ошибке, скорее всего, ваша система настроена правильно.

Теперь, чтобы проверить ваши данные. Напишите другой запрос, который вернет все строки из таблицы

$sql = "SELECT code FROM users WHERE 1 = ?";
$result = prepared_query($mysqli, $sql, [1])->get_result();
var_dump($result->fetch_all(MYSQLI_ASSOC));

и посмотрите, что у вас действительно есть в вашей базе данных. Вероятно, нет строк или другого значения кода. Подсказка: могут быть непечатные символы, которые могут помешать сопоставлению. чтобы выявить их, используйте очень удобную функцию rawurlencode(): она оставит все основные символы как есть, но преобразует все остальное в шестнадцатеричные коды, что облегчает их поиск

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