sit in a circle and chat happily

PHP 10・11日目~Lesson~

投稿日:2022-01-27
更新日:2022-03-24
php

共通関数ファイル:fanctions

<?php
// サニタイジング用関数を定義
// 短い名前で推奨されるオプション付きで実行する
function h($val) {
  return htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
}

function v($val) {
  echo '<pre>';
  var_dump($val);
  echo '</pre>';
}

入力画面

form1(ロジックファイル)

<?php
session_start();
// セッション変数利用開始
// 他のページと値を共有したい
session_regenerate_id(TRUE);
// セッションハイジャック対策
// PHPSESSIDの値を変更する
// 引数は常に「TRUE」を指定(省略しない!!)
// TRUE → 古いセッションファイルを削除
// 複数ページで処理する場合
// 始点となるファイルでPHPSESSIDの値を変更することが多い
require_once __DIR__ . '/functions.php';
// 共通関数の読み込み
// h関数とv関数を利用できるようにしている

// ▲ ▲ 下準備完了 ▲ ▲

// 「ロジック」と「ビュー(HTML)」を別ファイル管理している

// <ロジック担当者>と<ビュー担当者>は
// 画面に表示する値(変数)を共有しておかなければいけない

// 今回必要な値「名前」「件名」「内容」を用意している
$name    = isset($_SESSION['name'])    ? $_SESSION['name']    : NULL;
$subject = isset($_SESSION['subject']) ? $_SESSION['subject'] : NULL;
$body    = isset($_SESSION['body'])    ? $_SESSION['body']    : NULL;
// ◆初回アクセス時◆
// すべての変数に「NULL」を代入する
// ◆確認画面から戻ってきたときに活躍

// ビューファイル(HTML)を読み込む
require 'form1_view.php';
// ロジックが用意した変数を
// 適切な場所で
// h関数を使ってサニタイズしながら出力

form1_view(ビューファイル)

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>入力画面|フォーム</title>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
  <div class="header">
    <div class="inner">
      <h1>入力画面</h1>
    </div>
  </div>
  <div class="content">
    <div class="inner">
      <?php
      // form1.phpでは$errorが存在していないため
      // エラー表示部分の利用はない
      ?>
      <?php if (isset($error)) : ?>
        <div class="error">
          <ul>
            <?php foreach ($error as $val) : ?>
              <li><?php echo $val; ?></li>
            <?php endforeach; ?>
          </ul>
        </div>
      <?php endif; ?>

      <form action="form2.php" method="post">
        <dl>
          <dt>名前</dt>
          <dd>
            <input type="text" name="name" value="<?php echo h($name); ?>" size="50">
            <?php
            // 入力系パーツのvalue属性は初期値を担当
            // 初回アクセス時はnullなので
            // 初期値「空文字」で出力される
            // ◆後ほど活躍する予定
            ?>
          </dd>
          <dt>件名</dt>
          <dd>
            <input type="text" name="subject" value="<?php echo h($subject); ?>" size="50">
          </dd>
          <dt>内容</dt>
          <dd>
            <textarea name="body" cols="50" rows="10"><?php echo h($body); ?></textarea>
          </dd>
        </dl>
        <p>
          <input class="btn" type="submit" value="確認画面へ">
        </p>
      </form>
    </div>
  </div>
  <div class="footer">
    <div class="inner">
      <p class="copyright">© フォーム</p>
    </div>
  </div>
</body>

</html>

確認画面

form2(ロジックファイル)

<?php
session_start();
// セッション変数を利用できるようにする
require_once __DIR__ . '/functions.php';
// 共通関数を利用できるようにする
// h関数とv関数が利用できるようにする

v($_POST);

// 入力フォームから送られてきた値を代入
// ●ユーザ入力値を受け取る場合「GET」「POST」
// ●ユーザ入力値を保存する場合「COOKIE」「SESSION」
// ●ここではユーザ入力値を受け取る「POST」
$name    = isset($_POST['name'])    ? $_POST['name']    : NULL;
$subject = isset($_POST['subject']) ? $_POST['subject'] : NULL;
$body    = isset($_POST['body'])    ? $_POST['body']    : NULL;

// 全角スペースを半角スペースに変換
$name = mb_convert_kana($name, "s");
$subject = mb_convert_kana($subject, "s");
$body = mb_convert_kana($body, "s");
// str_replace関数を使った対応もあり

// trim関数:文字列の最初と最後のホワイトスペースを取り除く
//   半角スペース/タブ記号/改行コード
//   ※全角スペースは対象外
$name    = trim($name);
$subject = trim($subject);
$body    = trim($body);

// エラーを配列で管理
$error = [];

// 名前
if ($name == '') {
  // 名前が空文字の時の処理
  $error[] = 'お名前は必須項目です。';
} else if (mb_strlen($name) > 20) {
  // 名前が20文字を超えている時の処理
  $error[] = 'お名前は20文字以内でお願い致します。';
}

// 件名
if ($subject == '') {
  // 件名が空文字の時の処理
  $error[] = '件名は必須項目です。';
} else if (mb_strlen($subject) > 50) {
  // 件名が50文字を超えてる時の処理
  $error[] = '件名は50文字以内でお願い致します。';
}

// 内容
if ($body == '') {
  // 内容が空文字の時の処理
  $error[] = '内容は必須項目です。';
} else if (mb_strlen($body) > 500) {
  // 内容が500文字を超えている時の処理
  $error[] = '内容は500文字以内でお願い致します。';
}

if (count($error) > 0) {
  // エラーがあったら入力画面に戻る
  require 'form1_view.php';
} else {
  // エラーがなかったら確認画面表示
  // セッションに名前を保持させる → サーバで保管
  // ●確定したユーザ入力値を
  // ●他のページでも使えるようにする
  $_SESSION['name']    = $name;
  $_SESSION['subject'] = $subject;
  $_SESSION['body']    = $body;
  require 'form2_view.php';
  // 「form2_view.php」を呼び出す=確認画面に表示する
}

mb_convert_kana
カナを(“全角かな”、”半角かな”等に)変換する

form2_view(ビューファイル)

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>確認画面|フォーム</title>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
  <div class="header">
    <div class="inner">
      <h1>確認画面</h1>
    </div>
  </div>
  <div class="content">
    <div class="inner">

      <p>以下の内容でよろしければ送信ボタンを押してください。</p>
      <!-- サニタイジングして表示 -->
      <dl class="confirm">
        <dt>お名前:</dt>
        <dd><?php echo h($name); ?></dd>
        <dt>件名:</dt>
        <dd><?php echo h($subject); ?></dd>
        <dt>内容:</dt>
        <dd><?php echo nl2br(h($body)); ?></dd>
      </dl>

      <div class="confirm-btn">
        <p><a class="btn" href="form1.php">入力画面に戻る</a></p>
        <p><a class="btn" href="form3.php">送信する</a></p>
      </div>
    </div>
  </div>
  <div class="footer">
    <div class="inner">
      <p class="copyright">© フォーム</p>
    </div>
  </div>
</body>

</html>

完了画面

form3(ロジックファイル)

<?php
session_start();
// セッション変数を利用できるようにする
require_once __DIR__ . '/functions.php';
// 共通関数を利用できるようにする
// h関数とv関数が利用できるようにする

// サーバ上に値を持っていれば代入
// サーバ上に値を持っていなければエラーを出すためにNULLを代入
$name    = isset($_SESSION['name'])    ? $_SESSION['name']    : NULL;
$subject = isset($_SESSION['subject']) ? $_SESSION['subject'] : NULL;
$body    = isset($_SESSION['body'])    ? $_SESSION['body']    : NULL;


// unset関数:定義した変数の割当を削除する関数
// ●配列内の部屋を削除する
// ●セッション変数の部屋は明示的に削除しないと存在し続けてしまう
// ●使わなくなった部屋はunsetで削除する
unset($_SESSION['name']);
unset($_SESSION['subject']);
unset($_SESSION['body']);

// エラーチェック
$error = [];

// セッションに値が送られていなければエラーが出る
if ($name === NULL) {
  $error[] = '名前の値なし';
}

if ($subject === NULL) {
  $error[] = '件名の値なし';
}

if ($body === NULL) {
  $error[] = '本文の値なし';
}

// 受け取った値を使った処理:例)データベースへの登録など


if (count($error) > 0) {
  // エラーがあったらエラー画面表示
  require 'error_view.php';
} else {
  // エラーがなかったら完了画面表示
  require 'form3_view.php';
}

form3_view(ビューファイル)

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>完了画面|フォーム</title>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
  <div class="header">
    <div class="inner">
      <h1>完了画面</h1>
    </div>
  </div>
  <div class="content">
    <div class="inner">

      <p>以下の値で処理をしました。</p>

      <dl class="confirm">
        <dt>お名前:</dt>
        <dd><?php echo h($name); ?></dd>
        <dt>件名:</dt>
        <dd><?php echo h($subject); ?></dd>
        <dt>内容:</dt>
        <dd><?php echo nl2br(h($body)); ?></dd>
      </dl>

      <div class="content-footer">
        <p><a href="form1.php">入力画面に戻る</a></p>
      </div>
    </div>
  </div>
  <div class="footer">
    <div class="inner">
      <p class="copyright">© フォーム</p>
    </div>
  </div>
</body>

</html>

エラービューファイルerror_view

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>エラー|フォーム</title>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
  <div class="header">
    <div class="inner">
      <h1>エラー</h1>
    </div>
  </div>
  <div class="content">
    <div class="inner">
      <?php /* デバッグ用  */ ?>
      <?php /* ?>
      <?php if (isset($error)) : ?>
      <div class="error">
        <ul>
          <?php foreach ($error as $val) : ?>
          <li><?php echo $val; ?></li>
          <?php endforeach; ?>
        </ul>
      </div>
      <?php endif; ?>
      <?php */ ?>

      <p>セッションが切れました</p>
      <p><a href="form1.php">もう一度やり直してください。</a></p>
    </div>
  </div>
  <div class="footer">
    <div class="inner">
      <p class="copyright">© フォーム</p>
    </div>
  </div>
</body>

</html>
カテゴリー