MySQL整数フィールドがPHPで文字列として返される


127

MySQLデータベースにテーブルフィールドがあります。

userid INT(11)

だから私はこのクエリで自分のページにそれを呼び出しています:

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

その後、私は結果を処理するために:

$row=$result->fetch_assoc();

$id=$row['userid'];

今私がするなら:

echo gettype($id);

文字列を取得します。これは整数であるべきではありませんか?


2
MySQLクエリは、行タイプやその他の関連情報ではなく、行値を提供します。各表のセルにある生データのみ。PHPでこれを説明する必要があります
Dan Hanly

列のタイプが必要な場合は、こちらを参照してくださいforums.whirlpool.net.au/archive/526795
RichardTheKiwi

読者にとって、選択された回答には結果全体を反復することが含まれます。しかし、より良い解決策があります。 stackoverflow.com/a/1197424/5079380
Amr ElAdawy 2016

1
@DanHanly-技術的には、MYSQLクエリ(PHPの場合)はセル値の文字列表現を返します。32ビット整数のデータベースに保存される実際のセル値は... 32ビット整数であり、数字の文字列ではありません。 。
ToolmakerSteve

私にとっては、使用したときに$conn->query("your query")整数フィールドを文字列として取得しましたが、使用したとき$conn->prepare("your query")はデータベースにあるパラメータを取得しました
Bar Tzadok

回答:


129

PHPを使用してMySQLデータベースからデータを選択すると、データ型は常に文字列に変換されます。次のコードを使用して、整数に戻すことができます。

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

または関数を使用してintval()

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

79
PostgresのバックグラウンドからMySQLに来たので、これは非常に苦痛であると言う必要があると思います。Postgresで行をフェッチするときは、行配列の要素が適切なデータ型であることを確認してください。ここで、すべての要素を期待するデータ型に手動でキャストするコードを記述する必要があります。
GordonM、2011年

25
私はWindowsでLaravelとMysqlをまったく同じスキーマとデータベースサーバーでテストしました。Windowsでは主キーは整数として返され、Linuxでは文字列です。
AturSams 2014年

OKですが、何千ものフィールドを取得する場合はどうでしょうか。このプロセスにはしばらく時間がかかります。私の例では、各投稿のビュー数を取得してから、すべての投稿をテーブルに印刷します。ユーザーはView ascおよびdescで並べ替えることができますが、「1」から「9」で並べ替えられます。 "または"9 1など9999 " "91"、 "8111"、 "7"、 "ので、最初の場所であなたが持っている可能性が" ..."に"
KeizerBridge

@zehelvionこれまでに解決策を見つけたことがありますか?
フェリペフランシスコ

2
返されるすべてのフィールドは、文字列OR NULLになります
Liam

73

PHPにはmysqlnd(ネイティブドライバー)を使用します。

Ubuntuを使用している場合:

sudo apt-get install php5-mysqlnd
sudo service apache2 restart

Centosを使用している場合:

sudo yum install php-mysqlnd
sudo service httpd restart

ネイティブドライバは整数型を適切に返します。

編集:

@Jeroenが指摘したように、このメソッドはPDOの初期状態でのみ機能します。
@LarsMoellekenが指摘したように、MYSQLI_OPT_INT_AND_FLOAT_NATIVEオプションもtrueに設定すると、このメソッドはmysqliで機能します。

例:

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

この記事の証拠は見当たらない。mysqlndとmysqliで実行すると、明らかに文字列値が返されます。
Jeroen、2014

@Jeroenはよろしいですか?利用可能なドキュメントがたくさんあります。stackoverflow.com/questions/1197005/...
advait

はい。以下のコメントも見てください。これを自分でテストしましたか?現在のように、準備されたステートメントを使用する場合、mysqlndでも適切なタイプのみを返します。例: $link = mysqli_connect('localhost', 'root', ''); mysqli_set_charset($link,'utf8'); $result = mysqli_query($link,'SELECT CAST(\'3.51\' AS DECIMAL(3,2))'); $row = mysqli_fetch_assoc($result); var_dump($row);戻り値: array(1) { ["CAST('3.51' AS DECIMAL(3,2))"]=> string(4) "3.51" }
Jeroen

1
私の理解ではなく、PDOとMysqliで同じように動作するはずです。上記のコメントで投稿したリンクでさえ、準備されたステートメントでのみ機能し、OPによるインラインクエリではないことが明確に述べられています。そのページからの引用:しかし、これはPHP 5.3のみであり(PHP 5.3のバージョンがmysqlndでコンパイルされている場合(古いlibmysqlではない))、準備されたステートメントの場合のみ当てはまるようです:-(
Jeroen

7
mysqliには「MYSQLI_OPT_INT_AND_FLOAT_NATIVE」を使用することもできます
Lars Moelleken

20

私が見つけた最も簡単な解決策:

json_encodeに、数値のように見える値に実際の数値を使用させることができます。

json_encode($data, JSON_NUMERIC_CHECK) 

(PHP 5.3.3以降)。

または、IDをintにキャストすることもできます。

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

1
使用してjson_encode爪をチョークするために顕微鏡を使用してのようなことができればint型にキャストする文字列を。
LibertyPaul 2017

7
これはすべての郵便番号と電話番号を壊します。アプリにバグを紹介する良い方法。ソリューションは、値から推測しようとするのではなく、mysql列のデータ型を尊重する必要があります。
Max Cuttins 2018年

1
Max Cuttins、あなたのポイントは有効です。ただし、DBから期待されるすべてのデータ型を説明できる場合、これは最適な方法です。
Ifedi Okonkwo 2018

1
これは、 '06'のようなIDを持っている場合に害を及ぼします。このフラグはそれを6に変換します。これらのIDは後続ゼロを維持する必要があるため、これは誤りです。
Hassan Dad Khan

これは、UNIX_TIMESTAMP()たとえばによって作成された値の優れたソリューションです。
デビッド

18

私の解決策は、クエリ結果を渡し$rs、キャストデータのassoc配列を返すことです。

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

使用例:

$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

2
「NULL」以外の優れたソリューションは、settype()関数で使用される変数タイプでもあります。したがって、コードは、データベースによって返されるすべてのNULL値(gettype()== 'NULL'の値)を、 ''値を持つ 'string'タイプ、0値を持つ 'integer'タイプ、または0.0値を持つ 'float'タイプに変更します。is_null($ data [$ i] [$ name])がtrueの場合は、settypeを呼び出す必要はありません。
Winter Dragoness

私は首謀者のテクニックが好きですが、コーディングはもっと簡単です。
ToolmakerSteve

13

いいえ。テーブルで定義されているデータ型に関係なく、PHPのMySQLドライバは常に文字列として行の値を提供します。

IDをintにキャストする必要があります。

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

6
この動作を(直接)担当するのはPHPではなく、データベースドライバーです。PHPからPostgresデータベースに接続している場合は、適切なデータ型が返されます。
GordonM 2011年

5

特にブラウザでクエリ結果がJavaScriptに渡される場合、Chadの回答が気に入っています。JavaScriptは数値のようなエンティティを数値としてきれいに扱いますが、数値のようなエンティティを文字列として扱うには追加の作業が必要です。つまり、parseIntまたはparseFloatを使用する必要があります。

チャドのソリューションに基づいて構築し、私はこれを使用します。これはまさにまさに私が必要とするものであり、JavaScriptで簡単に処理できるようにJSONエンコードできる構造を作成します。

while ($row = $result->fetch_assoc()) {
    // convert numeric looking things to numbers for javascript
    foreach ($row as &$val) {
        if (is_numeric($val))
            $val = $val + 0;
    }
}

数値文字列を0に追加すると、PHPで数値型が生成され、型が正しく識別されるため、浮動小数点数が整数に切り捨てられません。


5

これPDO::ATTR_EMULATE_PREPAREStrue、接続でに設定されている場合に発生します。

ただし、注意して、falseパラメータを2回以上使用できないように設定します。また、返されるエラーメッセージの品質にも影響があると思います。


2

あなたはこれを行うことができます...

  1. mysql_fetch_field()
  2. mysqli_result :: fetch_field_directまたは
  3. PDOStatement :: getColumnMeta()

...使用する拡張機能によって異なります。mysql拡張は非推奨であるため、1つ目はお勧めしません。3つ目はまだ実験段階です。

これらのハイパーリンクのコメントは、タイプをプレーンな古い文字列からデータベースの元のタイプに設定する方法を説明するのに役立ちます。

一部のフレームワークもこれを抽象化します(CodeIgniterが提供する$this->db->field_data())。

結果の行をループして各行でis_numeric()を使用するなど、当て推量を行うこともできます。何かのようなもの:

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

これは、数字のように見えるものをすべて1に変えます...間違いなく完璧ではありません。


フロートには機能しません。それらはis_numericテストに合格します。最初にフロートをテストする必要があります。
マーティンファンドリエル

@MartinvanDrielまたは数値のみを含む任意の文字列(文字列である必要があります
-treeface

@MartinvanDriel追加してみてください:if (is_float()) { $value = (float)$value; }
adjwilli

2

私のプロジェクトでは、通常、で取得しmysql_fetch_assocたデータを「フィルタリング」する外部関数を使用します。

テーブルのフィールドの名前を変更して、格納されているデータ型を直感的に理解できるようにすることができます。

たとえば、各数値フィールドに特別な接尾辞を追加することができます場合useridですINT(11)あなたはそれを名前を変更することができますuserid_iかそれがある場合はUNSIGNED INT(11)名前を変更することができますuserid_u。この時点で、連想配列(で取得mysql_fetch_assoc)を入力として受け取る単純なPHP関数を記述し、それらの特別な「キー」で格納された「値」にキャストを適用できます。


1

準備されたステートメントが使用される場合、型は適切な場合はintになります。このコードは、各行が連想配列である行の配列を返します。fetch_assoc()すべての行に対して呼び出された場合と同様ですが、型情報は保持されます。

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

MySQLには他の多くの言語用のドライバーがあり、データを文字列に「標準化」し、ユーザーに任せて値をintなどに型キャストします。


1
プリミティブ型はかなり「標準」だと思いますか?言語固有のドライバーがその言語のニーズを満たすことができなかった場合、それは非常に残念です
Chung

1

私の場合、mysqlnd.so拡張機能がインストールされていました。しかし、私はしていませんでしたpdo_mysqlnd.so。したがって、問題はに置き換えることpdo_mysql.soで解決されましたpdo_mysqlnd.so


0

私は首謀者のテクニックが好きですが、コーディングはもっと簡単です:

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

また、結果セットではなくfalseを返すクエリのチェックも追加しました。
そして、null値を持つフィールドを持つ行をチェックします。
そして、目的のタイプが文字列である場合、私はその時間を無駄にしません-すでに文字列です。


ほとんどのphpコードでこれを使用することはありません。私はphpの自動型変換に依存しています。ただし、大量のデータをクエリして算術計算を実行する場合は、事前に最適な型にキャストするのが賢明です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.