前提・実現したいこと
クエリパラメータに渡されたカラムのみ値を更新する update.php を作っています。
DBへはmysqliを使用して接続しています。
カラムは二十数個ありますが、すべてを指定する必要はなく、指定されなかったカラムは更新しないようにしたいです。
パラメータ名とカラム名は対応しており、例えば「id=taro123&age=20&pref=Tokyo」とパラメータを渡した場合、
「UPDATE table SET age = 20, pref = 'Tokyo' WHERE id = 'taro123'」のようなSQLを発行したいです。
SQLインジェクション対策が必要で、できればSQL一文で実現したいと思っています。
※WHERE句のidをユーザーが指定できてしまう脆弱性は考えなくて構いません。
発生している問題・エラーメッセージ
SQLインジェクション対策のため、普段はprepare()を使用していますが、update.phpに指定できるパラメータの数も可変であるため、この場合にどのようにbind_param()に引数を与えればよいかわからず、止まってしまっています。
該当のソースコード
現状、以下のように一つずつissetでチェックして実装していますが、非常に冗長なため、もっと効率の良い方法はないでしょうか?
PHP
1$db = new mysqli($dbHost, $dbUser, $dbPasswd, $dbName); 2if ( isset($_POST['familyName']) ) { 3 $stmt = $db->prepare('UPDATE table SET familyName = ? WHERE id = ?'); 4 $stmt->bind_param('ss', $_POST['familyName'], $_POST['id']); 5 $stmt->execute(); 6 $stmt->close(); 7} 8if ( isset($_POST['firstName']) ) { 9 $stmt = $db->prepare('UPDATE table SET firstName = ? WHERE id = ?'); 10 $stmt->bind_param('ss', $_POST['firstName'], $_POST['id']); 11 $stmt->execute(); 12 $stmt->close(); 13} 14if ( isset($_POST['age']) ) { 15 $stmt = $db->prepare('UPDATE table SET age = ? WHERE id = ?'); 16 $stmt->bind_param('is', $_POST['age'], $_POST['id']); 17 $stmt->execute(); 18 $stmt->close(); 19} 20~~~以下、二十数カラム分続く~~~ 21$db->close();
考えた別解
- prepare()を使用することを諦めて、事前にパラメータが不正でないか全てチェックし、安全なSQL文を作ってquery()で実行
PHP
1$sql = 'UPDATE table SET '; 2if ( isset($_POST['familyName']) ) 3 $sql .= "familyName = {$_POST['familyName']}, "; 4if ( isset($_POST['firstName']) ) 5 $sql .= "firstName = {$_POST['firstName']}, "; 6~~~以下続く~~~ 7$sql .= "WHERE id = {$_POST['id']}"; 8$db->query($sql);
これもif文が連続し、あまり変わらない気がしています。。。
- 先にSELECTでデフォルト値を取得しておいて、全てのカラムを指定する
PHP
1$stmt = $db->prepare('SELECT * FROM table WHERE id = ?'); 2$stmt->bind_param('s', $_POST['id']); 3$stmt->execute(); 4$values = $stmt->get_result()->fetch_assoc(); 5$values['familyName'] == $_POST['familyName'] ?? $values['familyName']; 6$values['firstName'] == $_POST['firstName'] ?? $values['firstName']; 7~~~以下同~~~ 8$stmt = $db->prepare('UPDATE table SET familyName = ?, firstName = ?, ......... WHERE id = ?');
もっと美しい方法はありませんでしょうか?
またMySQL自体の扱いも不慣れで、直接の質問以外の箇所でも構文等に不自然、無駄な箇所があればご指摘頂けると幸いです。
どうか、皆様の知恵をお借りしたく、宜しくお願い致します。

回答2件
あなたの回答
tips
プレビュー
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。
2022/09/09 02:04