重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

xamppを標準インストールした環境にてPHPのPDOを利用したデータベース処理を試しているのですが、SELECTで取得した値がすべて文字列として返されます。

$db = new PDO("sqlite:sample.db");
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$rs = $db->query("select 1 as res");
$rs = $rs->fetch();

結果:
array(1) (
[res] => (string) 1
)

これに加え、やや強引なテストを行ってみたのですが、こちらも結果は同じく文字列となりました
$db = new PDO("sqlite:sample.db");
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$rs = $db->prepare("select ? as res");
$rs->bindValue(1, 1, PDO::PARAM_INT);
$rs->execute();
$rs = $rs->fetch();

この現象を回避するにはどのようにすればよいでしょうか。

A 回答 (3件)

sqliteだけかと思ってmysqlでも調べたら、取り出しデータは、全部とりあえずstring型ですね。


PDO側取り出し時は、csv から切り出す場合や、$_POSTデータなどと同じで、全部テキスト状態で渡ってくるためかと思われます。
SQLite3 や mysql5.0 以降であれば、カラムのメタ情報が取れるので、これで判断するとよいでしょう。
<?php
// fetch 後にメタ情報が取れる
$info = $rs->getColumnMeta($i) ;// $i は、select 節での記述順 0 開始

$info['native_type'] に実データ型が入ってます。SQLite では integer, string, double など、Mysql では、LONG, VAR_STRING, DOUBLE など。
それ以外のgetColumnMetaで得られる連想キーは、select節での記述形式によって変わるので、適宜var_dump などで調べてください。

結論としては、数値としての扱いが必要なら php側でキャストするしかないということではある。
ほとんどは、データベース内部で処理して、phpでは、表示用途でしかないことが多いから、気にしたことなかったけど。

参考URL:http://jp.php.net/manual/ja/pdostatement.getcolu …
    • good
    • 0
この回答へのお礼

現行のPDOにおいて単独では無理なようなので、カラムと照らし合わせて都度変換するなどで対応したいと思います。

お礼日時:2014/02/21 16:48

私も試してみました。



<?php
$db = new PDO('sqlite::memory:');
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db->query('CREATE TABLE test(num int)');
$db->query('INSERT INTO test VALUES(99)');
var_dump($db->query('SELECT num FROM test')->fetchColumn());

やっぱり

string(2) "99"

って出ちゃいますねぇ…

MySQLの場合はエミュレーション無効化によりこの問題は解決するのですが、SQLiteの場合はどうしようもなさそうです。手動で (int)$result もしくは intval($result) するなりしてキャストする必要があると思います。念のため

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

も行ってみましたが、最初からここはFALSEになっているようで無駄でした。
    • good
    • 0

以下のまとめでその現象の原因になっている「エミュレーション」について詳細に解説しているのでじっくりご覧ください。

MySQL向けに書いていますが、おそらくSQLiteでも同じような結果となるでしょう。

Qiita - PHPでデータベースに接続するときのまとめ
http://qiita.com/mpyw/items/b00b72c5c95aac573b71

以下のコードを推奨しておきます。EXCEPTIONモードにしたので全体をTryブロックでくくり、例外処理を行ってください。

$db = new PDO('sqlite:sample.db');
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

この回答への補足

ここで質問する前に同じサイトに行き着いたので、事前にその方法を試してみたのですが、やはり文字列として返ってきておりました。

補足日時:2014/02/19 20:24
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!