Я видел, как этот вопрос повторялся несколько раз при переполнении стека, но ни один из них не исследовал проблему (или, по крайней мере, так, как это полезно для меня).
Проблема заключается в том, что запрос БД должен возвращать целочисленные типы данных в PHP для целых столбцов. Вместо этого запрос возвращает каждый столбец как строковый тип.
Я обеспечил, что "PDO:: ATTR_STRINGIFY_FETCHES", если false, просто для того, чтобы убедиться, что результаты не передаются в строку.
Ответы, которые я видел:
Из моего исследования я понимаю, что это проблема с реализацией драйверов.
Многие источники утверждают, что родной драйвер MySQL не поддерживает возвращающие числовые типы. Это не похоже на то, поскольку он работает на Mac OS X. Если они не хотят сказать, что "родной драйвер MySQL на Linux не поддерживает эту функцию".
Это означает, что есть что-то особенное в драйвере/среде, которую я установил в Mac OS X. Я пытался определить различия, чтобы применить исправление, но я ограничен моим знанием того, как проверить эти вещи.
php -i
PDO_MySQL
Драйвер PDO для MySQL = > включен Версия API клиента = > 5.1.72
php -i
PDO_MySQL
Драйвер PDO для MySQL = > включен Версия API клиента = > mysqlnd 5.0.10 - 20111026 - $Id: e707c415db32080b3752b232487a435ee0372157 $
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false,
Любая помощь и опыт будут оценены:) Я обязательно отправлюсь туда, если найду ответ.
Решение состоит в том, чтобы убедиться, что вы используете драйвер mysqlnd для php.
При просмотре php -i
не упоминается "mysqlnd". В разделе pdo_mysql
будет что-то вроде этого:
pdo_mysql
PDO Driver for MySQL => enabled Client API version => 5.1.72
В большинстве руководств по установке для L/A/M/P предлагается apt-get install php5-mysql
, но собственный драйвер для MySQL устанавливается другим пакетом: php5-mysqlnd
. Я обнаружил, что это доступно с помощью ppa: ondrej/php5-oldstable.
Чтобы переключиться на новый драйвер (на Ubuntu):
apt-get remove php5-mysql
apt-get install php5-mysqlnd
service apache2 restart
Теперь php -i
явно укажет "mysqlnd" в разделе pdo_mysql
:
pdo_mysql
PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.10 - 20111026 - $Id: e707c415db32080b3752b232487a435ee0372157 $
Убедитесь, что PDO::ATTR_EMULATE_PREPARES
- false
(проверьте настройки по умолчанию или установите его): $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Убедитесь, что PDO::ATTR_STRINGIFY_FETCHES
- false
(проверьте настройки по умолчанию или установите его): $pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
† BIGINT со значением, превышающим 64-битный подписанный int (9223372036854775807), будет возвращаться в виде строки (или 32 бит в 32-битной системе)
object(stdClass)[915]
public 'integer_col' => int 1
public 'double_col' => float 1.55
public 'float_col' => float 1.5
public 'decimal_col' => string '1.20' (length=4)
public 'bigint_col' => string '18446744073709551615' (length=20)
Этот принятый ответ работает и, похоже, является наиболее популярным ответом в Google на этот вопрос. Моя проблема заключается в том, что мне нужно развернуть приложение в нескольких средах, и у меня не всегда есть возможность установить нужный драйвер, плюс мне нужно, чтобы десятичные числа были числовыми, а не строковыми. Поэтому я создал подпрограмму для ввода регистра case перед кодировкой JSON, которая легко модифицируется в соответствии с требованиями. Это как сбросить ядро с орбиты.
Сначала используйте команду "Показать столбцы из", чтобы получить столбцы из таблицы. MySQL запрос "ПОКАЗАТЬ КОЛОННЫ ИЗ таблицы, такие как 'colmunname'": вопросы
$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO
Затем поместите типы в массив, индексированный по имени столбца, чтобы упростить его повторение. Предполагается, что набор результатов из столбцов шоу находится в переменной с именем $ columns_from_table. http://php.net/manual/en/function.array-column.php
$column_types = array_column( $columns_from_table, 'Type', 'Field');
Затем мы хотим удалить скобку из типа, который будет что-то вроде varchar (32) или десятичного (14,6)
foreach( $column_types as $col=>$type )
{
$len = strpos( $type, '(' );
if( $len !== false )
{
$column_types[ $col ] = substr( $type, 0, $len );
}
}
Теперь у нас есть связанный массив с именем столбца в качестве индекса и форматированным типом в качестве значения, например:
Array
(
[id] => int
[name] => varchar
[balance] => decimal
...
)
Теперь, когда вы делаете выбор из таблицы, вы можете перебрать результаты и привести значение к соответствующему типу:
foreach( $results as $index=>$row )
{
foreach( $row as $col=>$value )
{
switch( $column_types[$col] )
{
case 'decimal':
case 'numeric':
case 'float':
case 'double':
$row[ $col ] = (float)$value;
break;
case 'integer':
case 'int':
case 'bigint':
case 'mediumint':
case 'tinyint':
case 'smallint':
$row[ $col ] = (int)$value;
break;
}
}
$results[ $index ] = $row;
}
Оператор switch может быть легко изменен для соответствия требованиям и может включать функции даты и т.д. Например, в моем случае третья сторона помещает значения валюты в базу данных в виде десятичного числа, но когда я получаю эти данные и мне нужно вернуть их как JSON, мне нужно, чтобы это были числа, а не строки.
Протестировано с PHP 7, 7.2 и JQuery 2, 3.