質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.62%

  • PHP

    19777questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • PDO

    330questions

    PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PDOの bindValue と execute を実行したときのデータベースとのやり取りについて教えてください。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,533

gununu

score 256

お世話になります。
現在、プリペアドステートメントについて調べている初心者です。
プリペアドステートメントの概要については「安全なSQLの呼び出し方」を読んで何となく理解しております。
「静的プレースホルダ」を使ってデータの取得・表示をしたいと考えております。
オプションで「PDO::ATTR_EMULATE_PREPARES => false」は設定しております。
「静的プレースホルダ」を使った場合のウェブアプリケーションとデータベースとのやり取りは「安全なSQLの呼び出し方」の解説図のようになる認識でおります。

データの取得・表示するには prepare → bindValue → execute → fetch の順で可能かと思います。
それぞれのメソッドについては、下記の処理を行っていると認識しております。

1.prepare
 文を実行する準備を行い、文オブジェクトを返す

2.bindValue
 値をパラメータにバインドする

3.execute
 プリペアドステートメントを実行する

【質問】
バインドした後にプリペアドステートメントを実行しても静的プレースホルダになるのでしょうか?
個人的にはバインドした後に実行したら動的プレースホルダと一緒なのでは?と疑問に思っております。
executeするときにprepareの文とbindValueの値をそれぞれ別々にデータベースに送っているのでしょうか?

ご存じの方いれば、ご教示ください。
よろしくお願いいたします。

【質問追記】※2015.03.13 19:11
質問がわからないとのご指摘を頂きました。
luckerさん ありがとうございます。
私が「バインド」や「プレイペアドステートメント」の意味を正しく理解していないのが原因かと思います。

それぞれの言葉を使わずに質問したいと思います。

下記のコードで動作するかと思います。

【手順1】prepare
$stmt = $pdo->prepare('SELECT name FROM fruit WHERE price=?')

【手順2】bindValue
$stmt->bindValue(1, 100);

【手順3】execute
$stmt->execute();

静的プレースホルダは「SELECT name FROM fruit WHERE price=?」と「1, 100」の命令文を別々にデータベースに送ってデータベース側で結合して実行しているとの認識でおります。

「手順3」では「SELECT name FROM fruit WHERE price=?」と「1, 100」の命令文を別々にデータベースに送っているのでしょうか?

【追記】※2015.03.13 20:33

※この質問は、luckerさんのお陰で解決済みです。

私の日本語力の無さが原因でした。
「安全なSQLの呼び出し方」に下記の説明があります。

パラメータ部分を示す記号「?」のことをプレースホルダと呼び、そこへ実際の値を割り当てることを「バインドする」と呼びます。

日本語力のない私は、「バインドする」=「値を埋め込む」と勘違いしました。

PHPマニュアルの「PDOStatement::bindValue」の説明には下記のようにバインドすると記述があります。

値をパラメータにバインドする

bindValueメソッドは値を埋め込む処理をしていると勘違いしたため、上記のような質問を致しました。
bindValueメソッドを記述したところでプレースホルダに値が埋め込まれて一つのSQL文になっているわけではないようです。
executeされることではじめてプリペアドステートメントが実行されます。
executeすることでprepareに記述したSQL文がデータベース側で構文解析され、その後に値を当てはめるようになるようです。
ありがとうございました。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

おっしゃりたいことがよく分からないのですが、
値をバインドする前に、プリペアドステートメントを“実行”したら、
一体何がDBに格納されるんでしょうか?

PDO::prepare()のことをおっしゃっているのなら、
これはステートメントをプリペアしているだけで実行はしていないと思いますが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/13 19:02

    質問がわかりづらく申し訳ございません。
    私が「バインド」と「プリペアドステートメント」などの言葉を誤った認識で使っているかもしれません。
    それぞれの言葉を使わずに質問したいと思います。

    下記のコードで動作するかと思います。

    【手順1】prepare
    $stmt = $pdo->prepare('SELECT name FROM fruit WHERE price=?')

    【手順2】bindValue
    $stmt->bindValue(1, 100);

    【手順3】execute
    $stmt->execute();

    静的プレースホルダは「SELECT name FROM fruit WHERE price=?」と「1, 100」の命令文を別々にデータベースに送ってデータベース側で結合して実行しているとの認識でおります。

    「手順3」では「SELECT name FROM fruit WHERE price=?」と「1, 100」の命令文を別々にデータベースに送っているのでしょうか?

    キャンセル

  • 2015/03/13 19:12

    疑問に持たれていること、なんとなくわかりました。

    PDOでプリペアした場合、バインドした値はステートメントには埋め込まずに別に送信されてDB側で評価されるようです。
    ですから、実際に実行されるSQL文をPDOやPDOStatementから取得することはできません。

    bindもprepareもDBに対しての指示ではなく、あくまでPDOStatementオブジェクトに対する指示です。
    ですから、バインドをプリペアより先に行っても、やはり静的プレースホルダとして動作しているようです。

    キャンセル

  • 2015/03/13 19:23

    luckerさん

    何度もご回答いただきありがとうございます。
    私は「bindValue=値の埋め込み」と誤解していたため、手順2の時点で既に値が埋め込まれているのかなと勘違いしておりました。
    埋め込みはせず別に送信されるんですね。
    お陰様で理解できました。
    ありがとうございました。

    キャンセル

  • 2015/03/13 19:27

    そうですね。正直のところ、動的プレースホルダなどという言葉があるのがややこしいかと思います。同じ“プレースホルダ”という言葉を使っていますが、全く別物ですね。

    キャンセル

  • 2015/03/13 19:38

    「安全なSQLの呼び出し方」を読んでも、静的プレースホルダと動的プレースホルダは別物と書いてありますし、SQLインジェクションにも係るみたいなので気をつけないといけませんね><
    もっと勉強します。
    ありがとうございました^^

    キャンセル

  • 2015/03/13 19:39

    申し訳ありません、補足と言いますか、訂正といいますか、

    PDO::ATTR_EMULATE_PREPARESがtrueの場合は、PHP側で埋め込みを行ってからDBに送信するようです。
    これは、プリペアドステートメントをサポートしないDB用のエミュレーションをPHP側で行うためのようですね。

    もちろん、いずれの場合でもbindParam実行時に値が埋め込まれるわけではないのですが、念のため訂正します。申し訳ありません。

    キャンセル

  • 2015/03/13 19:44

    PHP5.2以上ではPDO::ATTR_EMULATE_PREPARESがtrueになっていると調べたら書いてあったので、質問にも記載していおりますが、falseに設定しております。
    trueだと動的プレースホルダのような挙動になるという認識でおります。
    細かいところまでご指摘いただきありがとうございます^^

    キャンセル

  • 2015/03/13 19:50

    私はもう、DBアクセスはフレームワーク化してしまっているので、ほとんどこういったアクセスの部分のコードを書くことがなくなってしまい、少し知識があやふやでした。
    私も勉強になりました。有難うございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    19777questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • PDO

    330questions

    PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

  • トップ
  • PHPに関する質問
  • PDOの bindValue と execute を実行したときのデータベースとのやり取りについて教えてください。