web-dev-qa-db-fra.com

Le champ entier MySQL est renvoyé sous forme de chaîne dans PHP

J'ai un champ de table dans une base de données MySQL:

userid INT(11)

Donc, je l’appelle sur ma page avec cette requête:

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

Ensuite, pour gérer le résultat, je fais:

$row=$result->fetch_assoc();

$id=$row['userid'];

Maintenant si je le fais:

echo gettype($id);

Je reçois une chaîne. Cela ne devrait-il pas être un entier?

111
luca

Lorsque vous sélectionnez des données d'une base de données MySQL en utilisant PHP, le type de données sera toujours converti en chaîne. Vous pouvez le reconvertir en entier en utilisant le code suivant:

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

Ou en utilisant la fonction intval():

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

Utilisez le mysqlnd (pilote natif) pour php.

Si vous êtes sur Ubuntu:

Sudo apt-get install php5-mysqlnd
Sudo service Apache2 restart

Si vous êtes sur Centos:

Sudo yum install php-mysqlnd
Sudo service httpd restart

Le pilote natif renvoie les types entiers de manière appropriée.

Modifier:

Comme @Jeroen l’a souligné, cette méthode ne fonctionnera immédiatement avec PDO.
Comme @LarsMoelleken l'a signalé, cette méthode fonctionnera avec mysqli si vous définissez également l'option MYSQLI_OPT_INT_AND_FLOAT_NATIVE sur true.

Exemple:

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

Ma solution est de transmettre le résultat de la requête $rs et obtenez un tableau assoc des données converties comme retour:

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;
}

Exemple d'utilisation:

$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
17
mastermind202

La solution la plus simple que j'ai trouvée:

Vous pouvez forcer json_encode à utiliser des nombres réels pour des valeurs qui ressemblent à des nombres:

json_encode($data, JSON_NUMERIC_CHECK) 

(depuis PHP 5.3.3).

Ou vous pouvez simplement lancer votre identité sur un int.

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

Non. Quel que soit le type de données défini dans vos tables, le pilote MySQL de PHP fournit toujours les valeurs de ligne sous forme de chaînes.

Vous devez convertir votre identifiant en int.

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

J'aime la réponse de Chad, en particulier lorsque les résultats de la requête seront transmis à javascript dans un navigateur. Javascript traite proprement des entités numériques comme des nombres mais nécessite un travail supplémentaire pour traiter des entités numériques comme des chaînes. c'est-à-dire que vous devez utiliser parseInt ou parseFloat sur eux.

En m'appuyant sur la solution de Chad, j'utilise ceci et c'est souvent exactement ce dont j'ai besoin. Il crée des structures pouvant être encodées en JSON pour faciliter l'utilisation en 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;
    }
}

Ajouter une chaîne numérique à 0 génère un type numérique dans PHP et identifie correctement le type afin que les nombres à virgule flottante ne soient pas tronqués en nombres entiers.

Vous pouvez le faire avec ...

  1. mysql_fetch_field ()
  2. mysqli_result :: fetch_field_direct ou
  3. PDOStatement :: getColumnMeta ()

... en fonction de l'extension que vous souhaitez utiliser. Le premier n'est pas recommandé car l'extension mysql est obsolète. Le troisième est encore expérimental.

Les commentaires de ces liens hypertexte expliquent bien comment définir le type d'une chaîne ancienne et son type d'origine dans la base de données.

Certains frameworks résument également cela (CodeIgniter fournit $this->db->field_data() ).

Vous pouvez également faire des approximations - comme pour parcourir vos lignes résultantes et utiliser is_numeric () sur chacune. Quelque chose comme:

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

Cela transformerait tout ce qui ressemble à un chiffre en un seul… certainement pas parfait.

2
Chad Hedgcock

Dans mon projet, j'utilise généralement une fonction externe qui "filtre" les données récupérées avec mysql_fetch_assoc.

Vous pouvez renommer les champs de votre table de manière intuitive pour comprendre quel type de données est stocké.

Par exemple, vous pouvez ajouter un suffixe spécial à chaque champ numérique: si userid est un INT(11), vous pouvez le renommer userid_i Ou s'il s'agit d'un UNSIGNED INT(11) vous pouvez renommer userid_u. À ce stade, vous pouvez écrire une simple fonction PHP qui reçoit en entrée le tableau associatif (récupéré avec mysql_fetch_assoc)) Et appliquer le transtypage à la "valeur" stockée avec ceux-ci "clés".

2
Didax

Cela se produit lorsque PDO::ATTR_EMULATE_PREPARES est défini sur true sur la connexion.

2
Charlie

MySQL possède des pilotes pour de nombreuses autres langues, convertir des données en chaîne "standardise" les données et laisse à l'utilisateur le soin de transtyper les valeurs en int ou autres.

1
wolfgang

Dans mon cas mysqlnd.so extension avait été installée. MAIS je n'avais pas pdo_mysqlnd.so. Le problème a donc été résolu en remplaçant pdo_mysql.so avec pdo_mysqlnd.so.

1
Anton

Si des instructions préparées sont utilisées, le type sera int, le cas échéant. Ce code retourne un tableau de lignes, chaque ligne étant un tableau associatif. Comme si fetch_assoc() était appelé pour toutes les lignes, mais avec des informations de type préservées.

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;
}
1
Fredrik

Mettre un plus avant la variable fait aussi l'affaire,

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

De toute évidence, ce n’est pas la meilleure solution mais fonctionne lorsque vous n’avez pas accès à l’environnement pour installer un meilleur pilote.

0
Ebrahim Byagowi

J'aime technique de mastermind , mais le codage peut être plus simple:

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;
}

J'ai également ajouté la vérification de la requête renvoyant false plutôt qu'un ensemble de résultats.
Et rechercher une ligne avec un champ qui a une valeur nulle.
Et si le type souhaité est une chaîne, je ne perds pas de temps dessus, c'est déjà une chaîne.


Je ne me soucie pas de l'utiliser dans la plupart des codes PHP; Je viens de compter sur la conversion de type automatique de php. Mais si vous interrogez beaucoup de données, puis effectuez des calculs arithmétiques, il est judicieux d’utiliser à l’avance les types optimaux.

0
ToolmakerSteve