J'ai vu cette question répétée plusieurs fois sur Stack Overflow mais aucun n'explore suffisamment le problème (ou du moins d'une manière qui m'est utile)
Le problème est qu'une requête de base de données doit renvoyer des types de données entiers dans PHP pour les colonnes entières. Au lieu de cela, la requête renvoie chaque colonne sous forme de type chaîne.
J'ai veillé à ce que "PDO :: ATTR_STRINGIFY_FETCHES" si false juste pour s'assurer que les résultats ne sont pas convertis en chaîne.
Réponses que j'ai vues:
D'après mes recherches, je comprends qu'il s'agit d'un problème de mise en œuvre du pilote.
De nombreuses sources affirment que le pilote natif MySQL ne prend pas en charge le renvoi de types numériques. Cela ne semble pas vrai car cela fonctionne sur Mac OS X. Sauf s'ils veulent dire que "le pilote natif MySQL sur Linux ne prend pas en charge la fonctionnalité".
Cela implique qu'il y a quelque chose de spécial dans le pilote/l'environnement que j'ai installé sur Mac OS X. J'ai essayé d'identifier les différences afin d'appliquer un correctif mais je suis limité par ma connaissance de la façon de vérifier ces choses.
php -i
pdo_mysql
Pilote PDO pour MySQL => version d'API client activée => 5.1.72
php -i
pdo_mysql
Pilote PDO pour MySQL => version d'API client activée => 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,
Toute aide et expertise serait appréciée :) Je reviendrai certainement ici si je trouve la réponse.
La solution est de s'assurer que vous utilisez le pilote mysqlnd pour php.
Lors de l'affichage de php -i
, Il n'y aura aucune mention de "mysqlnd". La section pdo_mysql
Aura quelque chose comme ceci:
pdo_mysql
PDO Driver for MySQL => enabled Client API version => 5.1.72
La plupart des guides d'installation pour L/A/M/P suggèrent apt-get install php5-mysql
Mais le pilote natif pour MySQL est installé par un package différent: php5-mysqlnd
. J'ai trouvé que c'était disponible avec le ppa: ondrej/php5-oldstable.
Pour basculer vers le nouveau pilote (sur Ubuntu):
apt-get remove php5-mysql
apt-get install php5-mysqlnd
service Apache2 restart
Maintenant, php -i
Mentionnera explicitement "mysqlnd" dans la section pdo_mysql
:
pdo_mysql
PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.10 - 20111026 - $Id: e707c415db32080b3752b232487a435ee0372157 $
Assurez-vous que PDO::ATTR_EMULATE_PREPARES
Est false
(vérifiez vos valeurs par défaut ou définissez-le):$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Assurez-vous que PDO::ATTR_STRINGIFY_FETCHES
Est false
(vérifiez vos valeurs par défaut ou définissez-le):$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
† Les BIGINT avec une valeur supérieure à un entier signé 64 bits (9223372036854775807) seront renvoyés sous forme de chaîne (ou 32 bits sur un système 32 bits)
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)
Cette réponse acceptée fonctionne et semble être la réponse la plus populaire sur Google pour cette question. Mon problème est que je dois déployer une application dans plusieurs environnements et que je n'ai pas toujours la possibilité d'installer le bon pilote, et que j'ai besoin que les décimales soient numériques, pas des chaînes. J'ai donc créé une routine pour taper la casse avant l'encodage JSON, qui est facilement modifiée pour convenir. C'est un peu comme le mettre en orbite.
Tout d'abord, utilisez "afficher les colonnes de" pour obtenir les colonnes du tableau. requête mysql "SHOW COLUMNS FROM table like 'colmunname'": questions
$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO
Ensuite, placez les types dans un tableau indexé par le nom de la colonne pour faciliter l'itération. Suppose que l'ensemble de résultats des colonnes show se trouve dans une variable nommée $ column_from_table. http://php.net/manual/en/function.array-column.php
$column_types = array_column( $columns_from_table, 'Type', 'Field');
Ensuite, nous voulons supprimer la parenthèse du type, qui va être quelque chose comme varchar (32) ou décimal (14,6)
foreach( $column_types as $col=>$type )
{
$len = strpos( $type, '(' );
if( $len !== false )
{
$column_types[ $col ] = substr( $type, 0, $len );
}
}
Nous avons maintenant un tableau associé avec le nom de la colonne comme index et le type formaté comme valeur, par exemple:
Array
(
[id] => int
[name] => varchar
[balance] => decimal
...
)
Maintenant, lorsque vous effectuez votre sélection dans votre tableau, vous pouvez parcourir les résultats et convertir la valeur en type approprié:
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;
}
L'instruction switch peut être facilement modifiée pour convenir, et peut inclure des fonctions de date, etc. Par exemple, dans mon cas, un tiers pousse les valeurs monétaires dans la base de données sous forme décimale, mais lorsque j'attrape ces données et que je dois les renvoyer sous la forme JSON, j'ai besoin que ce soient des nombres, pas des chaînes.
Testé avec PHP 7, 7.2 et JQuery 2, 3.