データベース 6日目
投稿日:2022-02-08
更新日:2022-03-24
※編集の前に削除をやる
削除ページへのリンクを作成する
トップページから削除ページへのリンクを作成する。index.phpの該当箇所を下記のように変更する。
【変更前】
<td>削除</td>
【変更後】
<td><a href="delete.php?id=<?php echo h($data['id']); ?>"
onclick="return confirm('削除しますか?')">削除</a></td>
リンク先のURL「delete.php」の後ろにクエリ文字列を付加して編集用フォームにid番号を送る。このid番号を使って削除するレコードを決める。
onclick属性にJavaScriptで確認画面表示用のスクリプトを記述している。
商品情報の削除
<?php
$debug = true;
require_once dirname(__FILE__) . '/functions.php';
// クエリ文字列(GET)でID番号を受け取って
// DBから対象のレコードを削除する
$sql = '';
// デバック領域でSQL文を表示するので
// とりあえず空文字の入った変数を用意
if (isset($_GET['id'])) {
// クエリ文字列(GET)でID番号を受け取っている
$id = $_GET['id'];
// 使用しやすい変数名に値を代入
$dbobj = connectPractice();
// DB接続関数を呼び出して
// 接続許可証(オブジェクト)を変数$dbobjに代入
$sql = sprintf(
'DELETE FROM stationery WHERE id=%d',
mysqli_real_escape_string($dbobj, $id)
);
// セキュリティを考慮してSQL文を作成
// ・mysqli_real_escape_string関数
// ・sprintf関数
//★SQLインジェクション攻撃を防ぐ★
mysqli_query($dbobj, $sql) or die(mysqli_error($dbobj));
// SQL文(DELETE文)を実行
// DBから対象のレコードを削除
// ※【補足】
// 削除すると復元が難しくなるため
// 実際のシステムではあまり削除しない
// 削除用フィールドを用意して
// 0(有効扱い)/1(削除扱い)管理することが多い
// ビューファイルで表示するメッセージを作成
// 条件:mysqli_affected_rows関数
// 直前に実行したSQL文で影響を受けたレコード数を返す
// 今回はDELETE文で削除した件数を返す
// 削除OK:削除番号をmessage変数へ代入
// 削除NG:NGメッセージをmessage変数へ代入
if (mysqli_affected_rows($dbobj)) {
// 戻り値「1」:削除OK
// ※idフィールドは主キーなので
// 該当レコードがあった場合は1件のみ
$message = 'ID' . h($id) . 'を削除しました。';
} else {
// 戻り値「0」:削除NG
$message = 'ID' . h($id) . 'は存在しません。';
}
} else {
$message = '不正な処理です';
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="style.css" type="text/css" rel="stylesheet">
<title>商品管理システム</title>
</head>
<body>
<?php if ($debug) { ?>
<div class="debug">
<p>デバッグ用</p>
<p>$sql : <?php print $sql; ?></p>
<pre>$_GET : <?php var_dump($_GET) ?></pre>
</div>
<?php } ?>
<div id="container">
<div id="head">
<h1>商品削除</h1>
</div>
<div id="content">
<p><?php echo $message; ?></p>
<p><a href="index.php">一覧表示に戻る</a></p>
<!--#content--></div>
<!--#container--></div>
</body>
</html>
削除するレコードのIDを取得する
index.phpの削除リンクからクエリ文字列で送られてきたid番号をもとにレコードを削除する。まずはisset関数でid番号を取得できているか判定する。
if(isset($_GET['id'])){
【IDを取得できた時の処理】
}else{
【IDを取得できなかった時の処理】
}
idを取得できなかった時は、表示用変数$messageに「不正な処理です」と代入する。
$message = '不正な処理です';
データベースからレコードを削除する
idを取得できた場合は、DBからidを指定してレコードを削除する。
$sql = sprintf('DELETE FROM stationery WHERE id=%d',
mysqli_real_escape_string($dbobj, $id));
// セキュリティを考慮してSQL文を作成
// ・mysqli_real_escape_string関数
// ・sprintf関数
//★SQLインジェクション攻撃を防ぐ★
mysqli_query($dbobj, $sql) or die(mysqli_error($dbobj));
// SQL文(DELETE文)を実行
// DBから対象のレコードを削除
// ※【補足】
// 削除すると復元が難しくなるため
// 実際のシステムではあまり削除しない
// 削除用フィールドを用意して
// 0(有効扱い)/1(削除扱い)管理することが多い
mysqli_affected_rows()関数で削除した件数を取得する。「1」がかえってkるえば削除成功のメッセージを表示用変数$messageに代入する。
既に削除済み等で「0」が返ってきたときはその旨を伝えるメッセージを表示用変数に代入する。
// ビューファイルで表示するメッセージを作成
// 条件:mysqli_affected_row関数
// 直前に実行したSQL文で影響を受けたレコード数を返す
// 今回はDELETE文で削除した件数を返す
// 削除OK:削除番号をmessage変数へ代入
// 削除NG:NGメッセージをmessage変数へ代入
if (mysqli_affected_rows($dbobj)) {
// 戻り値「1」:削除OK
// ※idフィールドは主キーなので
// 該当レコードがあった場合は1件のみ
$message = 'ID' . h($id) . 'を削除しました。';
} else {
// 戻り値「0」:削除NG
$message = 'ID' . h($id) . 'は存在しません。';
}
実行結果を出力する
表示用変数$messageの内容を出力する。
<p><?php echo $message; ?></p>
// ・mysqli_real_escape_string関数
// ・sprintf関数
//★SQLインジェクション攻撃を防ぐ★
// $sql = sprintf(
// 'DELETE FROM stationery WHERE id=%d',
// mysqli_real_escape_string($dbobj, $id)
// );
// セキュリティを考慮してSQL文を作成
// ・mysqli_real_escape_string関数
// ・sprintf関数
// 1.文字列連結でSQL文作成
// $sql = 'DELETE FROM stationery WHERE id=' . $id;
// 5 or item='クレヨン'
// DELETE FROM stationery WHERE id=5 or item='クレヨン'
// 2.mysqli_real_escape_string関数と文字列連結
// $id = mysqli_real_escape_string($dbobj, $id);
// $sql = 'DELETE FROM stationery WHERE id=' . $id;
// 5 or item='クレヨン'
// DELETE FROM stationery WHERE id=5 or item=\'クレヨン\'
// 文字列開始のクォートがエスケープされたことで
// 不正なSQL文の実行を阻止できた
// 5 or id=3
// DELETE FROM stationery WHERE id=5 or id=3
// クォートを使わない不正な値の場合は
// 削除を実行されてしまう
// 5 or 0=0
// DELETE FROM stationery WHERE id=5 or 0=0
// SQLインジェクション攻撃でよく使う文字列
// 「 or 0=0」に対応しなければいけない
// この文字列でSQL文を実行されると
// 今回の場合は全レコードを削除される
// 3.mysqli_real_escape_string関数と
// sprintf関数を組み合わせる
$sql = sprintf(
'DELETE FROM stationery WHERE id=%d',
mysqli_real_escape_string($dbobj, $id)
);
// SQLインジェクションの対象になる
// 条件にはsprintf関数で「%d」を指定する
// ※「%s」を使うと意味ないので注意
// 5 or 0=0
// DELETE FROM stationery WHERE id=5
// 最初の数値「5」だけ使われて
// 残りの文字列は「%d」変換指定子によって
// 削除されている
// 結果第2条件の悪意ある条件が無視される