Почему в PHP mysqli_num_rows не возвращает целое число для запроса с 0 возвращаемыми строками?

#php #sql #mysqli

#php #sql #mysqli

Вопрос:

У меня странная проблема с mysqli_num_rows. При поиске этой проблемы я нашел только людей, у которых были проблемы, когда NULL возвращалось независимо ни от чего. Я также проверил официальную документацию для функции, и там говорится, что она возвращает целое число от числа строк, возвращенных запросом. Всякий раз, когда мой запрос возвращает 1 строку (он никогда не должен возвращать больше), он ведет себя так, как я ожидаю. Когда запрос возвращает 0 строк, я ожидаю, что функция вернет 0, но она возвращает NULL. Почему он не возвращает 0?

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

 function getArtistID($name) {
    global $conn; 
    $query = "SELECT artist_id FROM artist WHERE artist_name LIKE '${name}'";
    $result = mysqli_query($conn, $query);
    if ($result->num_rows) {
        $row = mysqli_fetch_assoc($result);
        return $row['artist_id'];
    } else {
        return 0;
    }
}
  

Комментарии:

1. Откуда вы знаете? Учитывая этот код, поведение, возвращает ли он 0 или null должно быть одинаковым. У меня такое чувство, что mysqli_query это тот, который возвращает null, а не mysqli_num_rows .

2. Не используйте global . Это явный показатель плохого дизайна, если он нужен вашему коду.

3. @tkausl да, это правда. Но мне любопытно, почему он не возвращает 0. В документах никогда не упоминается, что это возвращает NULL.

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

5. Люди часто говорят, что использование global плохо, потому что это затрудняет написание модульных тестов. Вы не можете протестировать функцию в ограниченной области видимости, если она ссылается на глобальные переменные. Неудобно создавать фиктивные объекты для глобальных. Смотрите phpunit.readthedocs.io/en/8.0/fixtures.html#global-state

Ответ №1:

Вот некоторый код, который я использовал для воспроизведения случая, когда num_rows кажется, что значение равно NULL:

 <?php
error_reporting(E_ALL);
$conn = new mysqli('127.0.0.1', 'root', null, 'test');
$sql = "SELECT * FROM dual";
$result = $conn->query($sql);
if ($result === false) {
  print "Error: {$conn->error}n";
}
$n = $result->num_rows;
echo "Dump the num_rows property: ";
var_dump($n);
  

Вывод:

 Error: No tables used

Notice: Trying to get property of non-object in /Users/bkarwin/Documents/SO/my.php on line 14
Dump the num_rows property: NULL
  

Уведомление связано с тем, что недопустимо обращаться к объектно-ориентированному свойству переменной, которая не является объектом. Это частый источник путаницы для разработчиков PHP, и это побочный продукт того факта, что PHP является свободно типизированным языком, и такие функции, как query() могут возвращать либо результирующий объект, либо логический скаляр.

query() Функция фактически вернула false как $result из-за некоторой ошибки. В моем коде я проверил наличие этой ошибки, а вы нет.

При выполнении mysqli::query() or mysqli::prepare() или mysqli_stmt::execute() каждый раз необходимо проверять наличие ошибок.

Что-то в вашем запросе вызвало ошибку. Вам решать проверить наличие ошибки и сообщить о ней.


Обновление: я отредактировал некоторый текст выше, чтобы сделать объяснение лучше, но из-за этого некоторые комментарии ниже могут показаться неуместными.

Комментарии:

1. Хорошо, я добавлю проверку. Но когда я запускаю запрос в phpmyadmin, я не получаю ошибок. Я также не получаю никакого странного поведения, когда он возвращает строки. В моей таблице действительно есть столбцы. Я не совсем понимаю вашу точку зрения здесь.

2. Мой запрос — это всего лишь один пример запроса, который генерирует ошибку. Я говорю, что ваш запрос, вероятно, генерирует какую-то другую ошибку. Дело в том, что вы не проверяете наличие ошибок.

3. Я предполагаю, что вы также не вызываете, error_reporting() чтобы включить уведомление, которое вы должны получать при вызове, $result->num_rows когда $result логическое значение равно false . Вы не можете запросить объектно-ориентированное свойство у переменной, если это не объект. Если переменная является скалярной, вы должны получить уведомление о правильной настройке уровня отчетов об ошибках. Это показано в моем примере кода.

4. Когда вы не настраиваете PHP для вывода уведомлений и сами не проверяете наличие ошибок, вы получаете множество запутанных эффектов, потому что вы понятия не имеете, когда произошли ошибки.

5. Разработчикам PHP это должно быть обязательным чтением для изучения phptherightway.com и выполняйте все рекомендации.

Ответ №2:

Я просто не могу понять, почему это возвращает NULL, а не 0.

Мы можем только догадываться, не видя выходных данных журнала; но, скорее всего, возвращаемое значение равно null, потому что вместо этого оно вызвало ошибку.

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