68 votes

Comment obtenir des types numériques depuis MySQL en utilisant PDO?

Je utilise PDO et MySQL, pour une raison quelconque lorsque je récupère des valeurs de la base de données qui sont de type int, le PDOStatement renvoie une représentation de chaîne du numéro et non une valeur de type numérique. Comment puis-je empêcher cela de se produire?

J'ai remarqué qu'il y a un attribut de la classe PDO : PDO::ATTR_STRINGIFY_FETCHES qui est censé prendre soin de cela mais, lorsque j'essaie de le modifier, il lance une erreur disant que l'attribut n'est pas valide pour le pilote MySQL.

Est-il normal d'obtenir des chaînes au lieu de nombres lors de la consultation d'une base de données?

68voto

Josh Davis Points 12974

Pour répondre à votre dernière question d'abord, "oui," malheureusement il est normal de recevoir des nombres en tant que chaînes. Comme le manuel cité par Pascal le dit, mysqlnd (PHP 5.3) renverra des types de données natifs à partir des instructions préparées, à condition que vous désactiviez l'émulation des instructions préparées de PDO.

new PDO($dsn, $user, $pass, array(
    PDO::ATTR_EMULATE_PREPARES => false
))

PDO::ATTR_STRINGIFY_FETCHES n'a aucun rapport avec MySQL.

Si vous regardez le bon côté des choses, c'est une bonne pratique d'utiliser des instructions préparées de toute façon, alors... ;)

4 votes

Si vous savez qu'un champ va être numérique, vous pouvez toujours ajouter zéro au champ. $values = $stm->fetch(); $values['numfield'] += 0; // Forcera la valeur à être numérique. Cela devrait fonctionner sur toutes les versions de php.

2 votes

Voici la réponse correcte. J'ai activé mysqlnd et je continue à obtenir des nombres convertis en chaînes de caractères. J'ai suivi cette réponse et obtenu les nombres correctement tels qu'ils devraient être.

0 votes

"il est bon de pratiquer l'utilisation des instructions préparées" Cela est trompeur. Il est seulement bon de connaître en détail les instructions préparées. Il n'y a pas de substitut à savoir ce que vous faites. À partir de là, vous pouvez savoir quand et quand ne pas l'utiliser. Aussi dans ce cas, nous comparons les requêtes préparées côté client par rapport aux requêtes préparées côté serveur. La raison d'imiter les requêtes préparées est qu'elles peuvent fournir d'autres fonctionnalités et des améliorations majeures des performances. Ce qui est le mieux dépend beaucoup des circonstances. Toutes mes bibliothèques permettent l'alternance afin que vous puissiez utiliser l'une ou l'autre en fonction des besoins.

41voto

Pascal MARTIN Points 195780

Je ne pense pas que l'utilisation des "chiffres" puisse être faite en PHP 5.2 :-(

En PHP 5.3, c'est devenu possible, si je me souviens bien, lorsque vous utilisez le nouveau (nouveau comme dans PHP >= 5.3) pilote mysqlnd (MySQL Native Driver).

Eh bien, après avoir fouillé dans mes favoris, j'ai trouvé cet article sur mysqlnd : PDO_MYSQLND: Les nouvelles fonctionnalités de PDO_MYSQL en PHP 5.3

Il dit ceci (citation) :

Avantages de l'utilisation de mysqlnd pour PDO

mysqlnd retourne les types de données natifs lors de l'utilisation de Déclarations Préparées côté serveur, par exemple une colonne INT est retournée en tant que variable entière et non pas en tant que chaîne. Cela signifie moins de conversions de données en interne.

Mais cela concerne uniquement PHP 5.3 (à condition que votre version de PHP 5.3 soit compilée avec mysqlnd (et non pas l'ancienne libmysql)), et semble être le cas uniquement pour les déclarations préparées :-(

Désolé...

Une solution serait d'avoir, du côté PHP, un système de mappage (comme un ORM -- voir Doctrine ; juste comme exemple d'ORM : je ne sais pas s'il fait ce que vous demandez) pour convertir les résultats provenant de la base de données en types de données PHP...

Et oui, c'est embêtant si vous voulez utiliser des opérateurs comme === et !==, qui sont sensibles au type...

7 votes

Sur Ubuntu, essayez sudo apt-get install php5-mysqlnd

0 votes

Moi aussi j'ai dû faire ce que @Alex a dit ici pour que php utilise mysqlnd en interne. +1 pour son commentaire.

0 votes

Avance rapide vers 2016, pour avoir des types de données corrects retournés par MySQL, pour PHP 7 sur CentOS/RHEL : yum install php70w-mysqlnd

31voto

Alexander Garden Points 808

La réponse de Pascal est correcte. J'ai eu un peu de mal à tout faire fonctionner. Voici ce que vous devez faire.

Tout d'abord, assurez-vous d'avoir mysqlnd installé et activé. Regardez php --info. Dans la section pdo_mysql, cela devrait ressembler à :

pdo_mysql

PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.8-dev - 20102224 - $Revision: 321

Si au lieu de voir mysqlnd dans la version de l'API Client, vous voyez une ligne comme...

Client API version => 5.5.29

...alors vous n'avez pas mysqlnd installé et opérationnel. Prenez d'abord soin de cela.

Deuxièmement, PDO utilise des déclarations préparées émulées par défaut pour toutes les connexions MySQL. Ridicule, mais c'est comme ça. Et vous n'obtiendrez que des types de données natifs si vous utilisez de vraies déclarations préparées (appelées "déclarations préparées côté serveur" dans le billet de blog lié, qui est maintenant ici). Vous devez donc définir PDO::ATTR_EMULATE_PREPARES sur false, comme ceci :

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Enfin, assurez-vous de ne pas avoir défini PDO::ATTR_STRINGIFY_FETCHES sur true.

$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

9 votes

Notez que le type DECIMAL sera toujours envoyé en tant que chaîne même avec cette configuration. Utilisation de la version 5.0.10 de mysqlnd ici.

4 votes

@Père, cela est fait délibérément pour éviter que le décimal ne devienne un flottant peu fiable en PHP.

14voto

R-Aamir Points 3525

Vous pourriez avoir mysqlnd installé, mais cela ne signifie pas qu'il est prêt à être utilisé par l'extension PDO régulière (pdo_mysql), c'est plus souvent le cas sur un hébergement partagé, alors assurez-vous d'activer l'extension nd_pdo_mysql, et aussi de désactiver une autre extension pdo_mysql car cela pourrait créer un conflit.

@capture d'écran

entrer la description de l'image ici

0voto

g33kz0r Points 3047

Si vous faites référence au système de types de MySQL, je pense que vous voudrez jeter un coup d'œil à la fonction PDOStatement->bindValue(). Cet appel a un troisième paramètre optionnel qui accepte un type de données explicite : http://us2.php.net/manual/en/pdostatement.bindparam.php#pdostatement.bindparam.examples

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X