web-dev-qa-db-ja.com

PHP + PDO + MySQL:PHPの整数および数値としてMySQLから整数および数値列を返すにはどうすればよいですか?

私はこの質問をStack Overflowで数回繰り返しましたが、問題を十分に調査したものはありません(または少なくとも私に役立つ方法で)

問題は、DBクエリが整数列に対してPHPで整数データ型を返す必要があることです。代わりに、クエリはすべての列を文字列型として返します。

結果が文字列にキャストされていないことを確認するためだけに、falseの場合、「PDO :: ATTR_STRINGIFY_FETCHES」を確認しました。

私が見た答え:

  • できません
    • いいえ、PHP/MySQLがインストールされたMac OS Xで動作しています
  • コード内のすべての値をキャストします
    • いいえ、私はそれをしません
  • 心配しないでください、PHPは緩やかに入力されます
    • 私のデータはJSONとして出力され、他の多くのサービスによって消費されます。一部のサービスは正しい形式のデータを必要とします

私の研究から、これはドライバー実装の問題であることを理解しています。

多くのソースは、MySQLネイティブドライバーが数値型を返すことをサポートしていないと主張しています。 Mac OS Xで動作するため、これは事実ではないようです。「Linux上のMySQLネイティブドライバーはこの機能をサポートしていません」と言わない限り。

これは、Mac OS Xにインストールしたドライバー/環境に何か特別なものがあることを意味します。修正を適用するために違いを特定しようとしていましたが、これらのことを確認する方法に関する知識に制限があります。

違い:

  • OS X上のPHPは、Home Brewを介してコンパイルおよびインストールされました。
  • Ubuntu上のPHPは、「apt-get install php5-dev」を介してインストールされました。
  • OS X上のPHPは、OS Xでも実行されているMySQLサーバーに接続しています
    • サーバーバージョン:5.1.71-logソースの配布
  • Ubuntu上のPHPはRackspace Cloud Databaseに接続しています
    • サーバーバージョン:5.1.66-0 + squeeze1(Debian)

Ubuntu環境

  • バージョン:10.04.1
  • PHP 5.4.21-1 + debphp.org〜lucid + 1(cli)(構築日:2013年10月21日08:14:37)
  • php -i

    pdo_mysql

    PDO Driver for MySQL =>有効なクライアントAPIバージョン=> 5.1.72

Mac OS X環境

  • 10.7.5
  • PHP 5.4.16(cli)(構築日:2013年8月22日09:05:58)
  • php -i

    pdo_mysql

    PDO Driver for MySQL =>有効なクライアントAPIバージョン=> mysqlnd 5.0.10-20111026-$ Id:e707c415db32080b3752b232487a435ee0372157 $

使用されるPDOフラグ

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,

どんな助けと専門知識もありがたいと思います:)答えが見つかったら、ここに間違いなく投稿します。

74
stephenfrank

解決策は、PHPでmysqlndドライバーを使用していることを確認することです。

Mysqlndを使用していないことをどうやって知るのですか?

_php -i_を表示すると、「mysqlnd」のno言及があります。 _pdo_mysql_セクションには次のようなものがあります。

_pdo_mysql

PDO Driver for MySQL => enabled Client API version => 5.1.72
_

どのようにインストールしますか?

L/A/M/Pのほとんどのインストールガイドでは_apt-get install php5-mysql_を推奨していますが、MySQLのネイティブドライバーは別のパッケージ_php5-mysqlnd_によってインストールされます。これはppa:ondrej/php5-oldstableで利用可能であることがわかりました。

新しいドライバーに切り替えるには(Ubuntuの場合):

  • 古いドライバーを削除します。
    _apt-get remove php5-mysql_
  • 新しいドライバーをインストールします。
    _apt-get install php5-mysqlnd_
  • Apache2を再起動します。
    _service Apache2 restart_

ドライバーが使用されていることを確認するにはどうすればよいですか?

これで、_php -i_は_pdo_mysql_セクションで明示的に「mysqlnd」に言及します。

_pdo_mysql

PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.10 - 20111026 - $Id:      e707c415db32080b3752b232487a435ee0372157 $
_

PDO設定

_PDO::ATTR_EMULATE_PREPARES_がfalseであることを確認してください(デフォルトを確認するか、設定してください):
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

_PDO::ATTR_STRINGIFY_FETCHES_がfalseであることを確認してください(デフォルトを確認するか、設定してください):
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

返される値

  • 浮動小数点型(FLOAT、DOUBLE)は、PHP floats。
  • 整数型(INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT†)は、PHP integers。
  • 固定小数点型(DECIMAL、NUMERIC)は文字列として返されます。

†64ビットの符号付き整数(9223372036854775807)より大きい値を持つBIGINTは、文字列(または32ビットシステムでは32ビット)として返されます

_    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)
_
112
stephenfrank

この受け入れられた回答は機能し、この質問に対するGoogleで最も人気のある回答のようです。私の問題は、アプリケーションを複数の環境に展開する必要があり、適切なドライバーをインストールできるとは限らないことに加えて、文字列ではなく数値である小数が必要なことです。そこで、JSONエンコードの前に大文字と小文字を入力するルーチンを作成しました。これは簡単に変更できます。それは軌道からそれを弱めるようなものです。

まず、「show columns from」を使用して、テーブルから列を取得します。 mysql query "'colmunname'のようなテーブルから列を表示":questions

$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO 

次に、列名でインデックス付けされた配列に型を取得して、簡単に反復できるようにします。 show columnsからの結果セットは、$ columns_from_tableという名前の変数にあると想定しています。 http://php.net/manual/en/function.array-column.php

$column_types = array_column( $columns_from_table, 'Type', 'Field');

次に、型から括弧を削除します。これは、varchar(32)またはdecimal(14,6)のようなものになります

foreach( $column_types as $col=>$type )
{
    $len = strpos( $type, '(' );
    if( $len !== false )
    {
        $column_types[ $col ] = substr( $type, 0, $len );
    }
}

これで、インデックスとして列名を、値としてフォーマットされた型を使用して、関連付けられた配列が作成されました。たとえば、

Array
(
    [id] => int
    [name] => varchar
    [balance] => decimal
    ...
)

これで、テーブルから選択を行うと、結果を反復処理し、値を適切な型にキャストできます。

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

Switchステートメントは、それに合わせて簡単に変更でき、日付関数などを含めることができます。たとえば、私の場合、サードパーティが通貨値を10進数としてデータベースにプッシュしますが、そのデータを取得し、 JSON、文字列ではなく数字にする必要があります。

PHP 7、7、7.2 and JQuery 2、3.でテスト済み.

2
Craig Jacobs