Похоже, что PDO всегда возвращает результаты базы данных в виде строк, даже если они являются числами или числами с плавающей запятой.
JSON-кодировщик PHP не выполняет никакого анализа типов : если значение содержится в строке PHP, оно помещается в кавычки, даже если оно может быть представлено как целое число или число с плавающей запятой.
С этим можно справиться двумя способами.
- Перед использованием
json_encode
.
- Измените потребителя JSON для приведения значения в число с плавающей точкой, прежде чем работать с ним.
Вот пример автоматического приведения на основе getColumnMeta
. Сначала давайте создадим фиктивную базу данных и вставим некоторые данные.
php > $pdo = new PDO('sqlite::memory:');
php > $pdo->exec('create table foo(a integer, b float, c text)');
php > $sh = $pdo->prepare('insert into foo(a, b, c) values(?, ?, ?)');
php > $sh->execute(array(1, 2.2, 'Three'));
php > $sh->execute(array(4, 5.55, 'Six'));
php > $sh->execute(array(7, 88.888, 'Nine'));
Теперь мы докажем, что данные есть, для нашей демонстрации:
php > $sh = $pdo->prepare('select * from foo where a = 4');
php > $sh->execute();
php > $row = $sh->fetch(PDO::FETCH_ASSOC);
php > var_dump($row);
array(3) {
["a"]=>
string(1) "4"
["b"]=>
string(4) "5.55"
["c"]=>
string(3) "Six"
}
Посмотрим, что скажет нам PDO о первом столбце.
php > print_r($sh->getColumnMeta(0));
Array
(
[native_type] => integer
[sqlite:decl_type] => integer
[flags] => Array
(
)
[name] => a
[len] => 4294967295
[precision] => 0
[pdo_type] => 2
)
Красивая. Я сделал это и для столбцов 1 и 2, которые возвращали «double» и «string» соответственно. Теперь давайте создадим карту имени столбца для ввода:
php > $cols = count($row);
php > $col_types = array();
php > while($cols-- > 0) {
$col_info = $sh->getColumnMeta($cols);
$col_types[ $col_info['name'] ] = $col_info['native_type'];
}
php > print_r($col_types);
Array
(
[c] => string
[b] => double
[a] => integer
)
Да, все наоборот, не имеет значения! Теперь давайте преобразуем наш ряд.
php > foreach($row as $k => $v) {
if($col_types[$k] == 'double')
$row[$k] = (float)$v;
if($col_types[$k] == 'integer')
$row[$k] = (int)$v;
}
php > var_dump($row);
array(3) {
["a"]=>
int(4)
["b"]=>
float(5.55)
["c"]=>
string(3) "Six"
}
php > echo json_encode($row);
{"a":4,"b":5.55,"c":"Six"}
Тад! Вы, вероятно, захотите обернуть это в удобный метод, это немного сложно сделать каждый раз вручную. Я мог бы также использовать columnCount , чтобы получить количество столбцов в наборе результатов, а не считать $row
.
много перебить? Вот пример непроверенный , который нацелен на конкретные имена столбцов и строит массив хэшей вручную в процессе.
$results = array();
$convert_columns = array( 'b' );
$sh = $pdo->prepare('select * from foo where a = 1');
$sh->execute();
while($row = $sh->fetch(PDO::FETCH_ASSOC)) {
foreach($convert_columns as $colname)
$row[$colname] = (float)$row[$colname];
$results[] = $row;
}