クロピグログ

職業訓練で学んだことまとめ

【DB授業八日目】MariaDB+PHP(続き4)

編集したデータをデータベースに登録

change.php

PHPの設定を表示させる

phpinfo();

 

●セッション変数を使えるようにする

session_start();

ユーザ識別用クッキーを発行するので出力処理より前で実行

なるべく上のほうに記述する

文字コードが「UTF8 with BOM」付きだとエラーになる可能性あり

文字コード「UTF8,UTF8N[テラパッドはN付きがなしって意味]」が安全

※「UTF8 with BOM」になっていたら「UTF8」にする

 

if (isset($_GET['id'])) {
  $id = $_GET['id'];
  $_SESSION['id'] = $id;
  SELECT * FROM stationery WHERE id=1
  修正する文房具フォームの初期値に使用する
  ラジオボタン選択済みを選ぶため
  $sql2 = sprintf虫食い部分を作る関数
   第1引数:フォーマット対象文字列
    'SELECT * FROM stationery WHERE id=%d'
   第2引数:対象文字列の虫食い部分に追加する値
    mysqli_real_escape_string($dbobj$id
  );

 

  mysql_query関数
  編集対象文房具の情報をDBから取得
  $stSet = mysqli_query($dbobj$sql2) or die(mysqli_error($dbobj));
  mysqli_affected_rows関数
  今回は編集対象文房具の件数を取得
  主キーを条件にしているので
  変数blに代入される値は
  $bl = mysqli_affected_rows($dbobj);
  $stData = mysqli_fetch_assoc($stSet); 連想配列にする

 

update.php

三項演算子で値が届いているか確認したうえで各変数に値を代入
・値が届いていたら「届いた値」を代入
・値が届いていなかったら「NULL」を代入
$id      = isset($_SESSION['id'])   ? $_SESSION['id']   : NULL;
$item    = isset($_POST['item'])    ? $_POST['item']    : NULL;
$price   = isset($_POST['price'])   ? $_POST['price']   : NULL;
$stock   = isset($_POST['stock'])   ? $_POST['stock']   : NULL;
$keyword = isset($_POST['keyword']) ? $_POST['keyword'] : NULL;
$maker   = isset($_POST['maker'])   ? $_POST['maker']   : NULL;

文字列の先頭・末尾にあるホワイトスペースを取り除く
ホワイトスペース:半角スペース、改行、タブ、NULL等
戻り値がstringなので値がすべて文字列になる
$id      = trim($id);
$item    = trim($item);
$price   = trim($price);
$stock   = trim($stock);
$keyword = trim($keyword);
$maker   = trim($maker);

商品を修正する際のSQL文用
必須項目が入力・選択されていない場合はDB接続しないのでとりあえず空文字
$sql = '';
HTML表示メーセージ用
状況によってメッセージが変わるのでとりあえず空文字
$message = '';
insert.phpの時は空文字だったが今回は値を代入
この後分岐が複数あるので一番可能性の高いものを初期値として代入
イレジュラーの場合のみ上書きすれば良い
$btn = '<a href="index.php">一覧に戻る</a>';
 
if ($id == '') {
  修正する商品IDが届かなかった場合の処理
  $message = '不正な処理です';
else {
  修正する商品IDが届いている場合の処理
  if ($item == '' or $maker == '') {
    必須項目が入力・選択されていない場合の処理
    $message = '必須項目を入力してください';
    $btn = '<a href="change.php?id=' . h($id. '" onclick="history.back(); return false;">フォームに戻る</a>';
    リンクで戻る場合(href属性)
    修正している商品のID番号をクエリ文字列で渡す
    履歴で戻る場合(onclick属性)←今回はこちら優先
    前回の状態が維持されて戻る
    今のブラウザはonclickとhrefがあるとonclickのページ遷移が優先される
    return false;あってもなくても挙動は変わらない
    一応hrefを使わないことを明示している保険のようなもの
  } else {
    必須項目が入力されている場合の処理
    $dbobj = mysqli_connect('localhost''Tanaka''Manager') or die(mysqli_error($dbobj));
    mysqli_select_db($dbobj'practice');
    mysqli_set_charset($dbobj'utf8');
    DB接続処理
    $sql = sprintf(
      'UPDATE stationery SET
      item="%s", price=%d, stock=%d, keyword="%s", maker=%d WHERE id=%d',
      mysqli_real_escape_string($dbobj$item),
      mysqli_real_escape_string($dbobjmb_convert_kana($price'n')),
      mysqli_real_escape_string($dbobjmb_convert_kana($stock'n')),
      mysqli_real_escape_string($dbobj$keyword),
      mysqli_real_escape_string($dbobjmb_convert_kana($maker'n')),
      mysqli_real_escape_string($dbobj$id)
    );
    ユーザ入力値を使ってSQL文を作成
    1.mysqli_real_escape_string関数でDBで文字列開始・終了を意味する
      クォート文字をエスケープ
    2.sprintfを使ってデータ型を指定する
      sprintf関数の虫食い部分
      %s:文字列
      %d:数値(10進数の整数)
    DBにSQL文を渡して対象商品を修正
    mysqli_query($dbobj$sql) or die(mysqli_error($dbobj));
    $message = 'ID' . h($id. 'を修正しました。';
  }
}
使い終わったセッションの部屋を削除
unset($_SESSION['id']);

 

・ユーザに入力してもらう値は「GET」

今回だと→商品名、価格、在庫など

・ユーザが入力しない値は「SESSION」

今回だと→ID

 

商品の削除

dekete.php

●1.文字列連結でSQL文作成

$sql = 'DELETE FROM stationery WHERE id=' . $id;

クエリ文字列id=の後に悪意ある値指定

1 or item='クレヨン'

受け取った値で作成されるSQL

DELETE FROM stationery WHERE id=1 or item='クレヨン'

 

●2.文字列連結でSQL文作成

$id = mysqli_real_escape_string($dbobj$id);
$sql = 'DELETE FROM stationery WHERE id=' . $id;

クォートをエスケープ

クエリ文字列id=の後に悪意ある値指定

1 or item='クレヨン'

DELETE FROM stationery WHERE id=1 or item=\'クレヨン\'

文字列を使った悪意ある値は防げるが、文字列を使わない悪意ある値は防げない

1 or id=5

DELETE FROM stationery WHERE id=1 or id=5

1 or 0=0

第2条件は常にtrueになる値なので全レコード対象の条件となる

UPDATEやDELETEが実行されると全件修正や全件削除になってしまう

 

●3.文字列連結を使わずにsprintfを使ってSQL文を構築【一番安全】

$sql = sprintf(
  'DELETE FROM stationery WHERE id=%d',
  mysqli_real_escape_string($dbobj$id)
);

sprintfを使ってSQL文を構築

条件に%dの数値を使う

※%sだと意味がないので注意

もちろんクォートのエスケープもする

悪意ある値

1 or id=5

DELETE FROM stationery WHERE id=1

1 or 0=0

DELETE FROM stationery WHERE id=1

 

SQL文でレコード削除実行

  mysqli_affected_rows関数
  直前のSQL文で影響を受けた件数を取得
  affected(影響を受ける)
  v(mysqli_affected_rows($dbobj));
  if (mysqli_affected_rows($dbobj)) {
    DELETE文による削除件数が
    0以外の場合はtrueとして扱う
    DELETE文による削除件数が
    0の場合はfalseとして扱う

    削除件数が0以外の時
    $message = 'ID' . h($id. 'を削除しました。';
  } else {
    削除件数が0の時
    $message = 'ID' . h($id. 'は存在しません。';
  }
else {
  削除用ID番号が届いていない場合の処理
  $message = '不正な処理です';
}