PHPでprepareやqueryを使用したいけど、よくわかりません。プレースフォルダーが上手くいきません。
このような悩みも解決します。実例をつけながら丁寧に解説します。
この記事を最後まで読んでprepareやqueryの特徴などを理解して、試して見て下さい。
PHPでデータベースにアクセスし、「値を操作」したい場合、「メソッド」が必要になります。
値を操作するとは、下記などです。
- 作成する
- 抽出する
- 削除する
- 更新する
メソッドとはDBを操作する命令文です。ここでのメソッドには2種類あります。下記になります。
- prepare
- query
PDOのprepareとqueryでSQL文を変数に格納する
DBにPDOでアクセスするインスタンスを、新しく作成し格納した変数を「$db」とします。
DBの中に「users」テーブルを作成しています。詳細は下記にしました。
id | name | score |
---|---|---|
1 | user_1 | 47 |
2 | user_2 | 24 |
PDOから出来たインスタンスには、SQLをリクエストするメソッドが2種類あります。先程言った2つになります。
SQL文を送るメソッド「prepare」
まずはprepareです。
- セキュリティが高い。
- 手間がかかる。
特徴はセキュリティ対策になる。リクエストするSQL文と、変化する値を別々にDBに送信するからです。
prepareの工程は下記です。
- SQL本文を決める(値が変化する)・・・メールで言う添付ファイル
- 変化する値を決める ・・・メールで言うパスワード
- 実行する ・・・メール送信
別々に送信するので、少し手間とリソースがかかります。
基本的に値が変化する場合は、こちらを使用しましょう。
prepareの基本構文を書く
$変数 = PDOから作成したインスタンスを格納した変数->prepare("SQL文");
$変数->bindValue(id,'変化する値',PDO::データ型);
$変数->execute();
SQL文を決めます。ここでは下記の4つから操作します。
- 作成する
- 抽出する
- 削除する
- 更新する
今回は抽出する「select」を使用します。データベースのカラム「name」の値を変更して使いまわしします。
SQLのselect構文の詳細は、下記の記事を参照してください。
プレース ホルダーは2種類あります。「?」と「:名前」です。
SQL文を入れた今回のコードは下記です。どちらでも構いません。
プレース ホルダー「?」の場合
$stmt = $db->prepare("select score from users where name=?");
プレース ホルダー「:名前」の場合
$stmt = $db->prepare("select score from users where name=:ユーザー");
usersテーブルからカラム「score」の値を取得します。カラム「name」が変化する値で、プレース ホルダーを使用しています。
インスタンス$dbのprepareメソッドで、SQL文を送る構文を変数「$stmt」に格納しました。
prepareのプレースホルダーを埋める構文
次にプレースホルダ―の値を埋めます。ここでは2つのメソッドがあります。
- bindValue
- bindParam
違い① bindValueで与える値は、直接値を指定しても、変数を使用してもOKです。bindParamで与える値は変数のみです。
違い② bindParamで実行する時にINT(数値型)を指定しても文字列になる。
違い③ bindValue もbindParamもexecuteで実行しますが、bindValue構文はその場で値が決まります。bindParamはexecuteする時に値が決まります。その前に変数の値が変われば、その値に変わるという事です。
prepareのプレースホルダーを埋めるbindValue構文
先程のSQLの「?」の部分の値を決めます。構文は下記です。
$stmt->bindValue(id,'値',オプション);
再程の変数$stmtから->bindValueメソッドを呼び出しています。()の中身は下記です。
- id:パラメータIDを指定します・・・「?」のホルダーが複数ある場合の番号、1つしかなければ1確定
- id:パラメータIDを指定します・・・「:名前」のホルダーがある場合、:名前を指定する
- 値:実際に入る値を指定します・・・ホルダーに入る値
- オプション:データの型を指定可能です・・・下記
オプションはデータ型を指定できます。種類は下記です。
- PDO::PARAM_STR ・・・デフォルトで文字列型
- PDO::PARAM_INT ・・・数値型
- PDO::PARAM_BOOL ・・・BOOLERN型
- PDO::PARAM_NULL ・・・NULL型
- ・・・・などなど
以上を踏まえて、今回のコードは下記になりました。
プレース ホルダー「?」の場合
$stmt->bindValue(1,'user_1',PDO::PARAM_STR);
プレース ホルダー「:名前」の場合
$stmt->bindValue(':ユーザー','user_1',PDO::PARAM_STR);
プレース ホルダー「?」の場合 「?」が一つしかないので、idは1
プレース ホルダー「:名前」の場合 、 一つしかないので、当然:ユーザーになります。
今回はカラム「name」が「user_1」の値の取得
「user_1」なので文字列型を指定して、バインドしようと思います。
これで、SQLの構文と、変化する値が決まりました。
prepareのプレースホルダーを埋めるbindParam構文
基本的にbindValueと同じです。違いの一つは下記でした。
違い① bindValueで与える値は、直接値を指定しても、変数を使用してもOKです。bindParamで与える値は変数のみです。
違い①bindParamの場合、値は変数のみ
プレース ホルダー「?」の場合
$user = 'user_1'
$stmt->bindParam(1,$user,PDO::PARAM_STR);
プレース ホルダー「:名前」の場合
$user = 'user_1'
$stmt->bindParam(':ユーザー',$user,PDO::PARAM_STR);
bindParamの場合、値の箇所を変数にしないとエラーとなります。変数$userにしました。
SQLリクエストをexecuteで実行する
最後はDBにリクエストしなければ、値を抽出する事は出来ません。
prepareでSQLリクエストするには、下記構文が必要です。
$変数->execute();
executeは実行するメソッドです。これでprepareでSQL文をリクエスト可能です。
prepareでSQLするコードをまとめると、下記になりました。
bindValueでSQL文を実行する
プレース ホルダー「?」の場合
$stmt = $db->prepare("select score from users where name=?");
$stmt->bindValue(1,'user_1',PDO::PARAM_STR);
$stmt->execute();
プレース ホルダー「:名前」の場合
$stmt = $db->prepare("select score from users where name=:ユーザー");
$stmt->bindValue(':ユーザー','user_1',PDO::PARAM_STR);
$stmt->execute();
bindParamでSQL文を実行する
プレース ホルダー「?」の場合
$user = 'user_1'
$stmt = $db->prepare("select score from users where name=?");
$stmt->bindParam(1,$user,PDO::PARAM_STR);
$stmt->execute();
プレース ホルダー「:名前」の場合
$user = 'user_1'
$stmt = $db->prepare("select score from users where name=:ユーザー");
$stmt->bindParam(':ユーザー',$user,PDO::PARAM_STR);
$stmt->execute();
基本的にbindValueと同じです。残りの違いは下記でした。
違い② bindParamで実行する時にINT(数値型)を指定しても文字列になる。
違い②により、すべて文字列になります。今回は「user_1」で文字列でしたが、INT型の数値だったとしたらexecuteの箇所で文字列型になります。
基本的にbindValueと同じです。残りの違いは下記でした。
違い③ bindValue もbindParamもexecuteで実行しますが、bindValue構文はその場で値が決まります。bindParamはexecuteする時に値が決まります。その前に変数の値が変われば、その値に変わるという事です。
違い③により、構文が下記だった場合
$user = 'user_1'
$stmt = $db->prepare("select score from users where name=:ユーザー");
$stmt->bindParam(':ユーザー',$user,PDO::PARAM_STR);
$user = 'user_2'
$stmt->execute();
executeの箇所に行くまでに$user変数の値が変わっています。bindValueであれば「user_1」、bindParamであれば「user_2」がクエリされます。
値が変化する場合は、prepareを使用しましょう。
bindParamを使用する時は、下記に注意しましょう。
- 値が文字列になる
- 途中で変数に値が入ると、SQLも変化する
SQL文を送るメソッド「query」
次はqueryです。queryは値が変化しない場合に使用します。
SQLと値を分ける事もなく、query自体実行まで行います。
prepareの工程は下記でした。
- SQL本文を決める(値が変化する)・・・メールで言う添付ファイル
- 変化する値を決める ・・・メールで言うパスワード
- 実行する ・・・メール送信
- 手間がかからず、簡潔に完了する
ではqueryの構文は下記になります。
$stmt = $db->query("select score from users where name=user_1");
値が変更しない、確定している場合にはqueryを使用しましょう。
PDOのprepareとqueryでSQL文を変数に格納するのまとめ
prepareのまとめ
prepareでSQL文を変数に格納する時は、値が変化する時
プレース ホルダー「?」の場合
$stmt = $db->prepare("select score from users where name=?");
$stmt->bindValue(1,'user_1',PDO::PARAM_STR);
$stmt->execute();
プレース ホルダー「:名前」の場合
$stmt = $db->prepare("select score from users where name=:ユーザー");
$stmt->bindValue(':ユーザー','user_1',PDO::PARAM_STR);
$stmt->execute();
変化する場所は「?」か「:名前」で場所を確保、場所を「 プレース ホルダー」と呼ぶ。
変化する値は「bindValue」か「bindParam」で指定する。
bindParamの注意点は下記
- 値は変数で指定しないとエラーになる
- 値が文字列になる
- 途中で変数に値が入ると、SQLも変化する
複数ある場合は、「?」の場合番号で、「:名前」の場合は名前で指定する。
データ型も指定できる。方は下記などあるが、STR(文字列)かINT(数値)がほとんど
- PDO::PARAM_STR ・・・デフォルトで文字列型
- PDO::PARAM_INT ・・・数値型
- PDO::PARAM_BOOL ・・・BOOLERN型
- PDO::PARAM_NULL ・・・NULL型
- ・・・・などなど
prepareは実行も必要。実行はexecuteで行う。
queryのまとめ
queryでSQL文を変数に格納する時は、値が変化しない時
$stmt = $db->query("select score from users where name=user_1");
この1行のみで完了。理由はbind不要(値が変化しない為)、実行もしてくれる為
これからもっとPHPのスキルを上げる為には
長くなりましたが、終わりです。難しいですが頑張って習得してください
短期間にスキルを上げて、転職したい、フリーランスになりたい場合はプログラミングスクールで学習するべきです。
劇的にプログラミングスキルが上がります、現役エンジニアから業界の事も聞けるのでオススメです。
PDOのprepareとqueryでSQL文を変数に格納した後は
格納した後はその値を取得したりも可能です。fetchやfetchAllを使用します。
詳しい事は下記の「PDOのfetchやfetchAllで値を抽出する」の記事をご覧ください