東京ロケット CEO のブログ

見習いサーバーサイドエンジニアのボクが、主にプログラミング学習の記録をしていきたいと思います。主にPHP。

疑問符プレースホルダー

SQL文が苦手なボクですが
いつものように
気づけばプロ並みPHP 改訂版--ゼロから作れる人になる!
をやっていると今まではスルーしていたんですが、素朴な疑問が。

UPDATE文のところで

UPDATE mst_staff SET カラム="値" WHERE code=1

codeが1のレコードの指定したカラムをこの値に変える。これは理解できます。
手持ちの
詳細!PHP 7+MySQL 入門ノート
にも同じことが書いてあります。

でも実習のコードは

 $sql='UPDATE mst_staff SET name=?,password=? WHERE code=?';

こんな感じです。まさに?です。

そこで毎度お馴染み鈴木先生に聞いて見ました。
するとslackで以下の回答が。

<?php
$name = 'test';
$pass = 'pass';
$code = '1234';

/*
 このときに最終的に実行したい SQL が下記のものだとすると..
 UPDATE mst_staff SET name = 'test', password = 'pass' WHERE code = '1234'

 作る方法は3つ
 */

// 方法 1
$sql = "UPDATE mst_staff SET name = '{$name}', password = '{$pass}' WHERE code = '{$code}'";
$stmt = $dbh->prepare($sql);
$stmt->execute();

/*
 直接 SQL に変数を埋め込む
 これはセキュリティー上よくない
 */

// 方法 2
$sql = 'UPDATE mst_staff SET name = ?, password = ? WHERE code = ?';
$stmt = $dbh->prepare($sql);
$data = [];
$data[] = $name;
$data[] = $pass;
$data[] = $code;
// もしくは
// $data = [$name, $pass, $code];
$stmt->execute($data);

/*
 疑問符を配列と置き換える
 この場合で言えば
 1回目の疑問符: name = ? が name = $data[0] と変換されて name = 'test'
 2回目の疑問符: pass = ? が pass = $data[1] と変換されて pass = 'pass'
 3回目の疑問符: code = ? が code = $data[2] と変換されて code = '1234'
 
 疑問符プレースホルダーという
 */

// 方法 3
$sql = 'UPDATE mst_staff SET name = :name, password = :pass WHERE code = :code';
$stmt = $dbh->prepare($sql);
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->bindValue(':pass', $pass, PDO::PARAM_STR);
$stmt->bindValue(':code', $code, PDO::PARAM_STR);
$stmt->execute();

/*
 名前をつけた箇所に変数を置き換える
 
 $stmt->bindValue(':name', $name, PDO::PARAM_STR);
 これは :name を $name で置き換えろという指示
 name = :name は name = $name となって name = 'test' となる
 
 名前付きプレースホルダーという
 */
Add Comment Co

はい。いつも通り丁寧でとても分かりやすいですね。

その後の解説も加えてまとめると、作り方は3つあります。

①そのまま埋め込む。-> これはセキュリティ上NGです。
②疑問符プレースホルダー ->これはSQLも綺麗でいいんですが、疑問符の位置と配列の添え字を合わせないといけないので、複雑なSQLだと
他の人が理解できない可能性もあります。
③ 名前付きプレースホルダー。->ジーズは確かこれでした。
結局は好みでいいようですが、プログラミングに関しては絶対服従のボクはもちろん鈴木先生オススメの②疑問符プレースホルダーでいきたいと思います。

しかし、書き方統一してほしいなー。