MySQL целочисленное поле возвращается как строка в PHP

У меня есть поле таблицы в базе данных MySQL:

userid INT(11)

Поэтому я звоню на мою страницу с этим запросом:

"SELECT userid FROM DB WHERE name='john'"

Затем для обработки результата я делаю:

$row=$result->fetch_assoc();

$id=$row['userid'];

Теперь, если я сделаю:

echo gettype($id);

Я получаю строку. Разве это не должно быть целым числом?

Ответ 1

Когда вы выбираете данные из базы данных MySQL с использованием PHP, тип данных всегда будет преобразован в строку. Вы можете преобразовать его обратно в целое число, используя следующий код:

$id = (int) $row['userid'];

Или с помощью функции intval():

$id = intval($row['userid']);

Ответ 2

Используйте mysqlnd (собственный драйвер) для php.

Если вы на Ubuntu:

sudo apt-get install php5-mysqlnd
sudo service apache2 restart

Если вы находитесь на Centos:

sudo yum install php-mysqlnd
sudo service httpd restart

Собственный драйвер возвращает целочисленные типы соответственно.

Редактировать:

Как отметил @Jeroen, этот метод будет работать только из коробки для PDO.
Как указал @LarsMoelleken, этот метод будет работать с mysqli, если вы также установите для параметра MYSQLI_OPT_INT_AND_FLOAT_NATIVE значение true.

Пример:

$mysqli = mysqli_init();
$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, TRUE);

Ответ 3

Мое решение состоит в том, чтобы передать результат запроса $rs и получить массив-получатель данных в качестве возвращаемого значения:

function cast_query_results($rs) {
    $fields = mysqli_fetch_fields($rs);
    $data = array();
    $types = array();
    foreach($fields as $field) {
        switch($field->type) {
            case 3:
                $types[$field->name] = 'int';
                break;
            case 4:
                $types[$field->name] = 'float';
                break;
            default:
                $types[$field->name] = 'string';
                break;
        }
    }
    while($row=mysqli_fetch_assoc($rs)) array_push($data,$row);
    for($i=0;$i<count($data);$i++) {
        foreach($types as $name => $type) {
            settype($data[$i][$name], $type);
        }
    }
    return $data;
}

Пример использования:

$dbconn = mysqli_connect('localhost','user','passwd','tablename');
$rs = mysqli_query($dbconn, "SELECT * FROM Matches");
$matches = cast_query_results($rs);
// $matches is now a assoc array of rows properly casted to ints/floats/strings

Ответ 4

Самое простое решение:

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

json_encode($data, JSON_NUMERIC_CHECK) 

(начиная с PHP 5.3.3).

Или вы можете просто указать свой идентификатор в int.

$row = $result->fetch_assoc();
$id = (int) $row['userid'];

Ответ 5

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

Вам нужно указать свой идентификатор в int.

$row = $result->fetch_assoc();
$id = (int) $row['userid'];

Ответ 6

Мне нравится ответ Чада, особенно когда результаты запроса будут переданы javascript в браузере. Javascript обрабатывает чисто числовые объекты как числа, но требует дополнительной работы для обработки числовых объектов, таких как строки. то есть должен использовать parseInt или parseFloat на них.

Основываясь на решении Chad, я использую это, и это часто точно то, что мне нужно, и создает структуры, которые могут быть закодированы JSON для удобства работы с javascript.

while ($row = $result->fetch_assoc()) {
    // convert numeric looking things to numbers for javascript
    foreach ($row as &$val) {
        if (is_numeric($val))
            $val = $val + 0;
    }
}

Добавление числовой строки в 0 создает числовой тип в PHP и правильно идентифицирует тип, поэтому числа с плавающей запятой не будут усечены в целые числа.

Ответ 7

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

Вы можете переименовывать поля в своей таблице, чтобы было понятно, какой тип данных хранится.

Например, вы можете добавить специальный суффикс для каждого числового поля: если userid является INT(11), вы можете переименовать его userid_i или если это UNSIGNED INT(11), вы можете переименовать userid_u. На этом этапе вы можете написать простую функцию PHP, которая получает в качестве входных данных ассоциативный массив (полученный с помощью mysql_fetch_assoc) и применяя отливку к "значению", хранящемуся с этими специальными "ключами".

Ответ 8

Вы можете сделать это с помощью...

... в зависимости от расширения, которое вы хотите использовать. Первое не рекомендуется, поскольку расширение mysql устарело. Третий все еще экспериментальный.

Комментарии к этим гиперссылкам хорошо объясняют, как установить ваш тип из простой старой строки в исходный тип в базе данных.

Некоторые фреймворки также абстрагируют это (CodeIgniter предоставляет $this->db->field_data()).

Вы также можете делать догадки - например, прокручивать полученные результирующие строки и использовать is_numeric() для каждого. Что-то вроде:

foreach($result as &$row){
 foreach($row as &$value){
  if(is_numeric($value)){
   $value = (int) $value;
  }       
 }       
}

Это превратило бы все, что выглядит как число в один... определенно не идеально.

Ответ 9

Если используются подготовленные операторы, тип будет там, где это необходимо. Этот код возвращает массив строк, где каждая строка является ассоциативным массивом. Например, если fetch_assoc() был вызван для всех строк, но с сохраненной информацией типа.

function dbQuery($sql) {
    global $mysqli;

    $stmt = $mysqli->prepare($sql);
    $stmt->execute();
    $stmt->store_result();

    $meta = $stmt->result_metadata();
    $params = array();
    $row = array();

    while ($field = $meta->fetch_field()) {
      $params[] = &$row[$field->name];
    }

    call_user_func_array(array($stmt, 'bind_result'), $params);

    while ($stmt->fetch()) {
      $tmp = array();
      foreach ($row as $key => $val) {
        $tmp[$key] = $val;
      }
      $ret[] = $tmp;
    }

    $meta->free();
    $stmt->close();

    return $ret;
}

Ответ 10

MySQL имеет драйверы для многих других языков, преобразовывая данные в строковые "стандартизованные" данные и оставляя их пользователю для ввода значений типа int или других

Ответ 11

В моем случае расширение mysqlnd.so было установлено. НО у меня не было pdo_mysqlnd.so. Итак, проблема была решена путем замены pdo_mysql.so на pdo_mysqlnd.so.

Ответ 12

Это происходит, когда PDO::ATTR_EMULATE_PREPARES имеет значение true для соединения.

Ответ 13

Помещение плюса перед переменной также делает трюк,

$a = "120";
$b = +$a;
echo gettype($b);

Очевидно, что это не лучший способ, но работает, когда у вас нет доступа к среде для установки лучшего драйвера.

Ответ 14

Мне нравится техника мастерства, но кодирование может быть проще:

function cast_query_results($result): array
{
    if ($result === false)
      return null;

    $data = array();
    $fields = $result->fetch_fields();
    while ($row = $result->fetch_assoc()) {
      foreach ($fields as $field) {
        $fieldName = $field->name;
        $fieldValue = $row[$fieldName];
        if (!is_null($fieldValue))
            switch ($field->type) {
              case 3:
                $row[$fieldName] = (int)$fieldValue;
                break;
              case 4:
                $row[$fieldName] = (float)$fieldValue;
                break;
              // Add other type conversions as desired.
              // Strings are already strings, so don't need to be touched.
            }
      }
      array_push($data, $row);
    }

    return $data;
}

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


Я не беспокоюсь об использовании этого в большинстве PHP-кода; Я просто полагаюсь на php автоматическое преобразование типов. Но если запрашивать много данных, а затем выполнять арифметические вычисления, разумно заранее привести к оптимальным типам.