PHP PDOでのMySQLから値を取り出す方法

このQ&Aのポイント
  • PHPの学習中にPDOオブジェクトを使用してMySQLから値を取得する方法を学びました。prepareメソッドでクエリを準備し、executeメソッドで実行します。
  • しかし、クエリ内に「?」が含まれる場合には問題が発生します。エスケープやバインド変数の方法を考える必要があります。
  • エスケープする方法やバインド変数として扱わない方法を知りたいです。他の解決策があれば教えてください。
回答を見る
  • ベストアンサー

【PHP】PDOでのMysqlから値を取り出す時に

現在phpを勉強しております。 PDOオブジェクトを生成し、 prepareメソッドでMySQLで実行するクエリをセットして executeメソッドで実行する。 というのを以下のようにしております $pdo= new PDO($dsn, $user, $password); $query = "SELECT * FROM table_name"; $stmt = $pdo->prepare(); $stmt->execute; で、この場合でも正常に動くのですが MySQL内のテーブルに「?」が含まれる場合だと $query = "SELECT * FROM table_name?test"; $stmt = $pdo->prepare(); $stmt->execute; とすると$queryの「?」をバインド変数とみなしてしまい エラーで「?の数とバインド先の変数の数を合わせろ」と出てしまいます。 ですので、「?」をエスケープしようと思い $query = "SELECT * FROM table_name\?test"; としたのですが、結局エスケープされず 同じエラーが出てしまいました。 エスケープできるならエスケープの方法か ?をバインド変数としてみなさない方法か または他の解決方法かを よろしければご教授願います。

  • PHP
  • 回答数2
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

少し、調べてみましたが、?は全てバインドされてしまうようです。 めぼしい情報も見つけられませんでした。 大概少し特殊な情報も、PHPマニュアルのコメント欄なんかに書いてあることがありますが、ソレも無いようです。 解決策は、 ・プリペアドステートメントを使わない ・テーブル名を変更する のどちらかしか無いと思います。 ただ、今後のメンテナンスなども含めて考えると、テーブル名に半角英数以外の文字が入っているのは 少し実装としては厄介ではないかなと思います。 規模が大きくなり、フレームワークを利用することになった場合、フレームワークのORマッパーを使うことになると思いますが、 その場合でも、プリペアドステートメントのところで毎回引っかかるようなことになりそうです。

phpthanperl
質問者

お礼

回答ありがとうございます。 prepareかexecuteはoptionでバインド無効にできるかな~と思い調べていましたが やはりありませんねぇ(^-^;) 確かに将来的にフレームワークを使ってデータベースを操作するとなると テーブル名にややこしい記号が入ってるとまたエラーで苦しむことになりそうなので おとなしくテーブル名を変更するようにします。 ありがとうございました!

その他の回答 (1)

回答No.1

そもそもテーブル名に?は利用できないと思いますが。

phpthanperl
質問者

補足

返信ありがとうございます。 phpmyadmin上からSQL実行、 またはperlのDBI上から、 PHPのPDOのprepare,execute経由でのSQL実行で試しましたが どのやり方でも、テーブル名に?を利用できました。 またデータベース名も可能でした。 記述し忘れていましたが 環境はMysql のVersion 5.5.25です。

関連するQ&A

  • PDOのprepareでLIKEの部分一致が使えません・・

    http://d.hatena.ne.jp/Sybian/20070521/p1 のサイトの例のように、LIKE '%文字列%' をprepareしようとしたのですが上手く結果が返りません。 PDOのプリペアステートメントは、 LIKEの部分一致や先頭一致に非対応なのでしょうか? $query="SELECT * FROM table WHERE id=:id OR like name='%:name%'"; $pdo=new PDO('mysql:host=localhost;dbname=database','user','password'); $stmt=$pdo->prepare($query); $stmt->bindValue(':id',$id,PDO::PARAM_INT); $stmt->bindValue(':name',$name,PDO::PARAM_STR); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC);

    • ベストアンサー
    • PHP
  • PDOがうまく動かない

    PDOがうまく動かなくて困っています。 $get_id = $_GET['id']; $stmt = $pdo->query("SELECT * FROM table where hoge = ':id'"); $stmt->bindValue(":id",$get_id, PDO::PARAM_STR); $stmt->execute(); if($row = $stmt->fetch()) { echo "あああ"; } $get_id = $_GET['id']; $stmt = $pdo->query("SELECT * FROM table where hoge = '$get_id'"); if($row = $stmt->fetch()) { echo "あああ"; } 2つ目は「あああ」と表示されるのですが、1つ目は何も表示されません。 よろしくおねがいします。

    • ベストアンサー
    • PHP
  • PDOクラスのprepareメソッドについて。

    いつもお世話になっております。 PHP5.2.5 1|$conn = new PDO($dsn,~略~);   //データベース接続 2|$sql = "略";             //SQL文 3|$stmt = $conn->prepare($sql);   // PDOStatementオブジェクトを返す 4|$stmt->bindParam(~略~);     //プレースホルダに変数をバインド 5|$stmt->execute();         //クエリ実行 という、よくある流れにおいて、 4行目のbindParamメソッドは、PDOクラスのメソッドではなく、 PDOStatementクラスのメソッドだと思うのですが、 これを、$stmt-> で呼び出せているのが、どうしてなのかがよく分からずにいます。 3行目で、PDOクラスのprepareメソッドを使うことで、 PDOStatementオブジェクトが返されるため、 その返り値を受け取った「$stmt」によって、 「$stmt->bindParam」できているという感じでしょうか? ★まず、この私の考え方について、合っているか間違っているか、 お聞きしたいと思います。(質問1) //=================================================== 恐らく、上記の考え方は「合っている」のだと思うのですが、 その上で、さらに質問をさせて頂くと、 ではなぜ、PDOStatementクラスを使う時に、 new PDOStatement; というようにしないのでしょうね? PDOクラスの1メソッドであるprepareメソッドを使うようにして、 PDOStatementクラスをインスタンス化しているのはなぜなのでしょう? (prepareメソッドはどういうコードになっているのでしょう?その中で、new PDOStatement という記述があるのでしょうね?) PDOのこのような仕様の背景には、どういう意図があるのか、 どなたか何か思い当たることなどありましたらご助言下さい。 (質問2)

    • ベストアンサー
    • PHP
  • バインドせずにPDOを使用すると

    PDOの使い方について教えてください。 例えば $id=3; $st = $pdo->prepare("SELECT * FROM user_table WHERE id=:id"); $st->bindValue(':id',$id, PDO::PARAM_INT); $st->execute(); を $id=3; $st = $pdo->prepare("SELECT * FROM user_table WHERE id='$id' "); $st->execute(); のようにバインドせずにPDOを使用するとSQLインジェクションなどのセキュリティ上問題があるのでしょうか? よろしくお願い致します。

    • 締切済み
    • PHP
  • PHP prepare フィールド名をエスケープ

    PHPのPDOを用いて、mysqlにクエリを発行する際、 prepare() と bindParam() でエスケープをしています。 しかし、フィールド名やテーブル名をエスケープしようとした場合、 プリペアドステートメントを利用することができません。 例えば 「SELECT * FROM table WHERE {$sample} = :test」 のような状態です。 このような場合、どうやって変数部分を安全にエスケープすべきなのでしょうか?

    • ベストアンサー
    • PHP
  • PHP PDO化作業中ORDERでソートできない

    WAMP初級者です。 いままでPEAR::DBを使って書いていたサイトがあり、PDOを利用するように書き換えていますが、いろいろ試してもorderでの並び替えが効いてくれません。どなたかアドバイス頂けないでしょうか。 該当箇所のみ切り出して例示いたします。 キーワード検索した結果画面で、$keywordはPOSTで渡って来ています。 ●うまくいく例(画面に期待したものが表示される) $connection=new PDO('mysql:host=localhost;dbname=test_db','root','root'); $connection->query('SET NAMES utf8'); $query="select * from test_tbl join test2_tbl using(Code) where NameW lik e :keyword"; $stmt=$connection->prepare($query); $stmt->bindValue(":keyword","%$keyword%",PDO::PARAM_STR); $stmt->execute(); ●これだと画面が真っ白になる(オーダーでソートしたいのですが。。) $orderKB="10K+10B"; $direction = "desc"; $connection=new PDO('mysql:host=localhost;dbname=test_db','root','root'); $connection->query('SET NAMES utf8'); $query="select * from test_tbl join test2_tbl using(Code) where NameW lik e :keyword order by :orderKB :direction"; $stmt=$connection->prepare($query); $stmt->bindValue(":keyword","%$keyword%",PDO::PARAM_STR); $stmt->bindValue(":orderKB", $orderKB, PDO::PARAM_STR); $stmt->bindValue(":direction", $direction, PDO::PARAM_STR); $stmt->execute(); ちなみに、10Kと10Bというのは数字データで合計した数字の高い順に並び替えを したいです。 初歩的な質問ですみませんが、どなたお助けいただけますと幸いです。 環境はApache/2.2.4 (Win32) PHP/5.4.22です 宜しくお願い致します。

    • ベストアンサー
    • PHP
  • PDOの使い方について

    PDOの使い方について教えてください。 例えば $st = $pdo->prepare("SELECT * FROM user_table WHERE id=:id"); $st->bindValue(':id',$id, PDO::PARAM_INT); $st->execute(); を $st = $pdo->prepare("SELECT * FROM user_table WHERE id='$id' "); $st->execute(); のように記載してはいけないのでしょうか? セキュリティ上問題があるのでしょうか? よろしくお願い致します。

    • 締切済み
    • PHP
  • PDO で IN句を利用することができません

    PDOでIN句を使用しているのですが、正しく動作しません。 $stmt = $pdo->prepare('SELECT * FROM hoge where id in (?)'); $stmt->bindValue(1, '123, 456, 789'); $stmt->execute(); var_dump($stmt->fetchAll()); fetchAllを行っても複数のレコードがかえってこず、ヒットした最初の1行のレコードしか取得することができません。PDOでIN句を使用することはできないのでしょうか? DBMSはMySQLを使用して、PHPは5.2.6を使用しています。 ちなみに $stmt = $pdo->prepare('SELECT * FROM hoge where id in (?, ?, ?)'); $stmt->bindValue(1, 123); $stmt->bindValue(2, 456); $stmt->bindValue(3, 789); $stmt->execute(); では、fetchAll で複数のレコードが返ってきます。 どうしてもpreparedで単一のIN句を使いたいのですが、何か良い方法はありますでしょうか?

    • 締切済み
    • PHP
  • PDOでMYSQL

    WHERE区の値をbindValueしているのですが、結果が取得できません。 ちなみにエラーになるわけでも文字化けを起こすわけでもありません。 $name = '太郎'; $sql = 'SELECT * FROM table WHERE name = :name; $sth = $dbh->prepare($sql); $sth->bindValue(':name', $name, PDO::PARAM_STR); $sth->execute(); $result = $sth->fetchAll(); print_r($result); いろいろ試してたところ、日本語だと結果を取得しないようで SQLデータの「太郎」となっていた箇所を「tarou」に変更し 変数の部分だけ変更したところ結果を取得できました。 $name = 'tarou; 基本の構文は合っていると思うのですが単純に日本語の指定が できないのでしょうか? PHPとMYSQLは全てUTF-8でバージョンは下記の通りです。 PHP:5.3.8 MYSQL:Client API version mysqlnd 5.0.8-dev - 20102224 - $Revision: 310735 $ PDO: PDO drivers mysql, odbc, sqlite, sqlite2 Client API version mysqlnd 5.0.8-dev - 20102224 - $Revision: 310735 $

    • ベストアンサー
    • PHP
  • PHPのPDOについて

    例えば手続き型でしたら、値をデータベースに追加するとき $sql = sprintf( 'INSERT INTO member SET id=%d, message="%s" ', mysql_real_escape_string($id), mysql_real_escape_string($message) ); mysql_query($sql) or die(mysql_error()); など「mysql_real_escape_string」を使って多少なりともセキュリティーをかけると思うのですが、PDOですと下記に書かれている以外に見たことないのですが、「mysql_real_escape_string」などはやらなくても大丈夫ということなのでしょうか? PDOの場合 $sql = 'INSERT INTO member SET id=?, message=?'; $stmt = $db->prepare($sql); $stmt->execute(array($id, $message)); 色々調べてみたのですがいまいち分からないためよろしくお願いします。

    • ベストアンサー
    • PHP