クロピグログ

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

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

商品管理システムを作成

登録されている商品一覧を表示

index.php

●デバック用の領域の表示・非表示

$debug = true;

 

●自分で作成した関数を読み込んで利用できるようにする「function.php」の読み込み

require_once dirname(__FILE__. '/functions.php';「/」忘れ注意

◇h関数:XSS対策用関数

◇v関数:デバック用関数

・require:読み込み失敗時にFatal Errorで処理停止

・_once:同じファイルの複数回読み込み禁止

 うっかり複数回読み込んでも2回目以降は無視

・dirname(__FILE__) = __DIR__ どちらも同じ意味

 今動いているファイルのフォルダまでの絶対パスが返ってくる

 __FILE__:PHPがあらかじめ用意している定数 

 マジカル定数

 今動いているファイルまでの絶対パス

・dirname関数:引数で指定したファイルパスからファイル名を除いてディレクトリ(フォルダ)までの絶対パスを返す関数

 

●データベース接続

$dbobj = mysqli_connect(
  'localhost'DBサーバの場所
  'Tanaka', DBユーザ名
  'Manager'  DBパスワード
) or die('DB接続できませんでした');

◇ORの特殊な使い方

・第1条件:mysqli_connect関数の戻り値を変数dbobjに代入して変数dbobjの値で真偽値の判断

 接続OK:mysqliオブジェクトがあるので「true」

 第2条件は見ない

 接続NG:falseなので「false」

 第2条件を見る

・第2条件:die関数は引数を出力してPHPの処理を停止

 

●実行するSQL文を変数に代入

$sql = 'SELECT * FROM stationery';

複雑なSQL文になった時に変数を使ってSQL文をデバック表示できるように

 

●mysqli_query関数でSQL文を実行

$resultSet = mysqli_query($dbobj$sql) or die(mysqli_error($dbobj));

・戻り値としてstationeryテーブル情報が返る

・変数resultSetに代入

◇ORの特殊な使い方

・第1条件:SQL文の結果を変数resultSetに代入

 変数resultSetの値で真偽値判定

 SQL文実行でOKでテーブル情報あり「true」

 第2条件を見ない

 SQL文実行NGで「false」を第2条件を見る

・第2条件:die関数実行

 die関数の引数に「mysqli_error関数」

 mysqli_error関数:DBエラーメッセージをDBから取得して返す関数

 DBから取得したエラーメッセージを出力してPHPの処理を停止

 

●mysqli_affected_rows関数

$bl = mysqli_affected_rows($dbobj); int(6)今回だと商品一覧

直前に実行したSQL文の結果を返す

直前に実行したSQL文がSELECT文の場合、取得したレコードの件数を返す

変数名bl(bool値の意味)はHTML側で真偽値代わりに使っているので変数名blだが、あまりよくないかも...

数値が入っていることがわかる変数名のほうがよい(例:$resultCount等)

 

bodyの中

  <?php if ($debug) : ?>
    <div class="debug">
      <p>デバック用</p>
      <p>$spl:<?php print $sql?></p>
      <p>$bl:<?php v($bl); ?></p>
    </div>
  <?php endif?>

  <div id="container">
    <div id="head">
      <h1>商品一覧 <?php echo $bl?></h1>
    </div>
    <div id="content">
      商品があったらtrue  商品がなかったらelse
      <?php if ($bl) : ?>
        <table>
          <tr>
            <th>ID</th>
            <th>商品名</th>
            <th>価格</th>
            <th>在庫</th>
            <th>キーワード</th>
            <th>メーカー</th>
            <th>編集</th>
            <th>削除</th>
          </tr>
          <?php while ($data = mysqli_fetch_assoc($resultSet)) : ?>
            <tr>
              <td><?php echo h($data['id']); ?></td>
              <td><?php echo h($data['item']); ?></td>
              <td><?php echo h($data['price']); ?></td>
              <td><?php echo h($data['stock']); ?></td>
              <td><?php echo h($data['keyword']); ?></td>
              <td><?php echo h($data['maker']); ?></td>
              <td>編集</td>
              <td>削除</td>
            </tr>
          <?php endwhile?>
        </table>
      <?php else : ?>
        <p>商品がありません</p>
      <?php endif?>
      <p class="btn"><a href="entry.php">新規作成</a></p>
    </div><!--#content-->
  </div><!--#container-->

 

●htmlspecialchars関数

  $str = '<h1>テスト</h1>';
  echo $str表示結果:テスト
  echo htmlspecialchars($str); 表示結果:<h1>テスト</h1>

・HTMLで意味のある記号を実態参照に置き換えてXSS攻撃を防ぐ関数

XSS攻撃:scriptタグを使ったJSによる攻撃

XSS対策:HTMLタグを無効化して防ぐ

・第1引数:変換対象文字列

・第2引数:シングルクォートを実体参照するかどうか

 ダブルクォートは指定なしでも実体参照

 scriptタグ内で出力した際にJSの文字列を無効化するため

・第3引数:文字コード指定

 違う文字コードも文字列の場合に第3引数で指定した文字コードに変換

・戻り値:タグを無効化した文字列

 htmlspecialcharsでユーザ入力値を無害化(サニタイジング)する

 これを使うタイミングは出力直前で行う

 複数サニタイジングはNG

例)

<h1>あああ</h1>

1回目無害化:&lt;h1&gt;あああ&lt;/h1&gt;

2回目無害化:&amplt;h1&ampgt;あああ&amplt;/h1&ampgt;

 

htmlspecialchars関数の名前が長いので自前でh関数を定義して使うことが多い

 

●scriptも含む対策例

  <?php
 $code = "alert('aaa');";
  ?>
  <script>
    <?php echo $code?>
  </script>
  <script>
    <?php echo htmlspecialchars($code); ?> 
     アラート表示されちゃう
  </script>
  <script>
    <?php echo htmlspecialchars($code, ENT_QUOTES); ?>
     アラート表示されない
  </script>

 

HTMLでのエスケープ処理をする関数

引数に変数も配列も両方受け取ってサニタイジングできる関数として定義
function h($var)
{
  if (is_array($var)) {
    配列で受け取った時の処理
    return array_map('h'$var);
    array_map:配列内の各部屋に第1引数で指定した関数を実行する
    今回はh関数自身を読み込んでる
  } else {
    配列じゃない時の処理
    return htmlspecialchars($var, ENT_QUOTES, 'UTF-8');
  }
}