【初心者必見】PHPでWebフォーム作成!フォームを作るときの注意点も抑えよう。

プログラミング

今回はphpでWebフォームの使い方については学んで行きましょう。

この記事を読んでわかること
  • HTMLでのフォームコーディング
  • phpでのPOSTの送受信
  • フォームを作成する際の注意点

この記事で学べないことはDBへの接続などは今回の記事では扱わないです。

後々DBへの接続の記事を出す予定です

事前準備

phpが実行できる環境を準備が必要です。

  • MAMP
  • XAMPP
  • Docker

など、自分の使いやすい環境で大丈夫です。

phpのバージョンはPHP 8.0.12を使用しています。

全体のファイル構成

.
├── README.md
└── web-form
    ├── common
    │   └── head.php
    ├── compleat.php
    ├── index.php
    └── receive.php
  • index.php フォーム画面
  • receive.php 確認画面
  • compleat.php 完了画面
  • common/head.php 共通のheadタグ

フォームの作成

まずは、index.phpを作ってフォームを作成して行きます。

<!DOCTYPE html>
<html lang="ja">
<body>
  <div class="form-area container-sm mt-5">
    <h1>Webフォーム入力テスト</h1>
    <form action="receive.php" method="post" class="mt-4">
      <div class="mb-3">
        <label for="my_name" class="form-label">名前</label>
        <input type="text" class="form-control" name="my_name">
      </div>
      <div class="mb-3">
        <label for="my_age" class="form-label">年齢</label>
        <input type="number" class="form-control" name="my_age">
      </div>
      <div>
        <label for="email" class="form-label">メールアドレス</label>
        <input type="text" class="form-control" name="email" value="">
      </div>
      <div class="mt-3">
        <input type="submit" class="btn btn-primary" value="データの送信">
      </div>
    </form>
  </div>
</body>
</html>

ひとまず、phpは気にせずにhtmlタグのみだけ記述していきます。

クラスが付与されているのは、Bootstrapを使ってスタイルの調整をしていくので今はこのままで問題ないので、一旦おいておきましょう。

フォームで情報を送るために、formタグで囲って上げる必要があります。

  • 送信項目
    • 名前
    • 年齢
    • メールアドレス

スタイルの適用

次に、head.phpを作成していきます。

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Webフォーム</title>
  <link href="<https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css>" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>

今回、Bootstrapでデザインを調整していくので、CDNで読み込みます。

<link href="<https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css>" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

次に、head.phpを読み込む必要があるので、index.phpへ読み込みます。

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

<?php include './common/head.php';?> // 追加

<body>
  <div class="form-area container-sm mt-5">
    <h1>Webフォーム入力テスト</h1>
    <form action="receive.php" method="post" class="mt-4">
      <div class="mb-3">
        <label for="my_name" class="form-label">名前</label>
        <input type="text" class="form-control" name="my_name">
      </div>
      <div class="mb-3">
        <label for="my_age" class="form-label">年齢</label>
        <input type="number" class="form-control" name="my_age">
      </div>
      <div>
        <label for="email" class="form-label">メールアドレス</label>
        <input type="text" class="form-control" name="email" value="">
      </div>
      <div class="mt-3">
        <input type="submit" class="btn btn-primary" value="データの送信">
      </div>
    </form>
  </div>
</body>
</html>

上記のような、画面が表示されていれば、手順通り進んでいます。

データの送受信

データの送信と受信の機能を作って行きましょう。

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $name = htmlspecialchars($_POST['my_name'], ENT_QUOTES);
  $age = (int)$_POST['my_age'];
  $email = htmlspecialchars($_POST['email'], ENT_QUOTES);
}

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

<?php include './common/head.php';?>

<body>
  <div class="container-sm mt-5">
    <h1>データ確認画面</h1>
    <form action="compleat.php" method="post">
      <input type="hidden" name="my=name" value="<?php echo $name?>">
    <input type="hidden" name="my=age" value="<?php echo $age?>">
    <table class="table">
      <tbody>
        <tr>
          <th scope="row">名前</th>
          <td><?php echo $name?></td>
        </tr>
        <tr>
          <th scope="row">年齢</th>
          <td><?php echo $age?></td>
        </tr>
        <tr>
          <th scope="row">メールアドレス</th>
          <td><?php echo $email?></td>
        </tr>
      </tbody>
    </table>
    <div class="mx-auto">
      <input type="submit" class="btn btn-primary" value="完了">
    </div>
  </form>
</div>
</body>

</html>

ここでは、受信したものをそのまま表示しているだけなので、index.phpで入力した情報が表示されていればて動作確認OKです。

<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $name = htmlspecialchars($_POST['my_name'], ENT_QUOTES);
  $age = (int)$_POST['my_age'];
  $email = htmlspecialchars($_POST['email'], ENT_QUOTES);
}
?>

POSTで送られてきたかのチェックを行い、POSTで送信されてきた場合は、各変数へ情報を格納します。

この時、不要な文字や使用できない文字をエスケープ処理する必要があります。

こういった対策のことをXSS対策と言います。

XSSとは?

クロスサイトスクリプティング(XSS)とはWebアプリケーションへのサイバー攻撃手法で、代表的なサイバー攻撃のひとつです。この攻撃は適切な対策を行うことで回避可能なサイバー攻撃です。

データの入力チェック、正規表現

現状、入力内容のチェックを行っていないので、どのような形でもデータの送受信を行うことができます。

そうなると、管理や情報の信用度などにも関わってくるので、入力項目のチェックを行います。

今回は、正規表現を用いて、データチェックを行います。

まず、正規表現とはなにか?

  • 「いくつかの文字列を一つの形式で表現するための表現方法」
  • 文字列のパターンを表現する表記方法
  • 文字列の検索やパターンを表現する

といった表現をされることが多いです。

さっそく正規表現を用いてデータ整合性のチェックを行って行きましょう。

チェックの流れは、

  1. 名前のチェック
  2. 年齢のチェック
  3. メールアドレスのチェック

それぞれの項目をチェックし、条件に引っかかるものがあった場合はエラーメッセージを表示できるように$errorの配列にメッセージを格納する。

名前のチェックと条件

  • 名前の情報が入力されているか
  • 文字数が20文字以下であるか
if (empty($name)) {
	$error['name'] = '名前を入力してください';
	// name length check
	if(mb_strlen($name) > 20) {
	  $error['name'] = '名前は20文字以内で入力してください';
	}
}

年齢のチェックと条件

  • 年齢の情報が入力されているか
  • 入力値が0から120の間であるか
  • 半角で入力されているか
if (empty($age)) {
    $error['age'] = '年齢を入力してください';
  } elseif ($age < 0 || $age > 120) {
    $error['age'] = '年齢は0以上120以下で入力してください';
  } elseif (!preg_match('/^[0-9]+$/', $age)) {
    $error['age'] = '年齢は半角数字で入力してください';
  }
}

メールアドレスのチェック

  • メールアドレスの情報が入力されているか
  • メールアドレスの形式で情報が入力されているか
if (empty($email)) {
    $error['email'] = 'メールアドレスを入力してください';
  } elseif (!preg_match('/^[a-zA-Z0-9.!#$%&\\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/', $email)) {
    $error['email'] = 'メールアドレスを正しく入力してください';
  }
}

エラーがある場合は入力フォームへ戻す

各項目のチェックを行ったあと、$errorが空の場合は確認画面を表示し、空でない場合は入力画面へ戻します。

// エラーがある場合前の画面へ戻す
if (isset($error)) {
  // エラーメッセージをセッションに保存
  $_SESSION['error'] = $error;
  header('Location: index.php');
  exit;
}

この時、エラーメッセージを保持したまま画面へ戻したいので、Sessionを用いて情報を返します。

Sessionを使ってエラーメッセージを表示

sessionを開始するには、session_start();の記述が必要になります。

なので、recive.phpにセッション開始に記述を行います。

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $name = htmlspecialchars($_POST['my_name'], ENT_QUOTES);
  $age = (int)$_POST['my_age'];
  $email = htmlspecialchars($_POST['email'], ENT_QUOTES);

  session_start(); // 追加

・・・ // 入力項目のチェック

// エラーがある場合前の画面へ戻す
if (isset($error)) {
  // エラーメッセージをセッションに保存
  $_SESSION['error'] = $error;
  header('Location: index.php');
  exit;
}

?>

これで、セッションヲ使うことができるので次に、index.phpにエラーメッセージを表示できるように、要素の準備をしていきます。

エラーメッセージの表示

下記の内容を任意の場所に追加します。通常エラーは画面上部に出すので、今回はフォームの上部に表示します。

<?php if (!empty($error)) : ?>
  <div class="mt-3">
    <ul class="alert alert-danger" role="alert">
      <?php foreach ($error as $err) : ?>
        <li class="mx-2"><?php echo $err; ?></li>
      <?php endforeach; ?>
    </ul>
  </div>
<?php endif; ?>

ここまでで一度表示を確認してみましょう。

何も入力せずに、データの送信ボタンを押すと、下記のような表示になっていれば動作確認OKです。

今のままでは、ボタンを押すと入力データが消えてしまいます。

なので、先程のエラーメッセージと同様にセッションにデータを保持させ、入力したデータがある場合は、入力欄に表示するようにしましょう。

まずは、receive.phpにセッションのデータを保持する記述をします。

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $name = htmlspecialchars($_POST['my_name'], ENT_QUOTES);
  $age = (int)$_POST['my_age'];
  $email = htmlspecialchars($_POST['email'], ENT_QUOTES);

  session_start();

	$_SESSION['name'] = $name; // 追加
  $_SESSION['age'] = $age; // 追加
  $_SESSION['email'] = $email; // 追加

・・・ // 入力項目のチェック

// エラーがある場合前の画面へ戻す
if (isset($error)) {
  // エラーメッセージをセッションに保存
  $_SESSION['error'] = $error;
  header('Location: index.php');
  exit;
}

?>

次に、index.phpにセッションのデータがあるときは、入力欄に表示する処理を書きます。

<form action="receive.php" method="post" class="mt-4">
      <div class="mb-3">
        <label for="my_name" class="form-label">名前</label>
        <input type="text" class="form-control" name="my_name" value="<?php if (!empty($_SESSION['name'])) {
                                                                        echo $_SESSION['name'];
                                                                      } ?>">
      </div>
      <div class="mb-3">
        <label for="my_age" class="form-label">年齢</label>
        <input type="number" class="form-control" name="my_age" value="<?php if (!empty($_SESSION['age'])) {
                                                                          echo $_SESSION['age'];
                                                                        } ?>">
      </div>
      <div>
        <label for="email" class="form-label">メールアドレス</label>
        <input type="text" class="form-control" name="email" value="<?php if (!empty($_SESSION['email'])) {
                                                                      echo $_SESSION['email'];
                                                                    } ?>">
      </div>
      <div class="mt-3">
        <input type="submit" class="btn btn-primary" value="データの送信">
      </div>
    </form>

追加の内容は、inputタグ内の、valueに各項目のセッションのデータを表示することです。

<?php if (!empty($_SESSION['name'])) {
  echo $_SESSION['name'];
} ?>

これでセッションのデータが存在する場合は、入力欄にデータが表示されるようになります。

では、ここまでの全体のコードを見ていきましょう。

index.php

<?php
session_start();
// $_SESSION['error']がある場合は、エラーメッセージを表示する
if (isset($_SESSION['error'])) {
  $error = $_SESSION['error'];
  // エラーメッセージをクリア
  unset($_SESSION['error']);
}
?>

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

<?php include './common/head.php';?>

<body>
  <div class="form-area container-sm mt-5">
    <h1>Webフォーム入力テスト</h1>
    <?php if (!empty($error)) : ?>
      <div class="mt-3">
        <ul class="alert alert-danger" role="alert">
          <?php foreach ($error as $err) : ?>
            <li class="mx-2"><?php echo $err; ?></li>
          <?php endforeach; ?>
        </ul>
      </div>
    <?php endif; ?>
    <form action="receive.php" method="post" class="mt-4">
      <div class="mb-3">
        <label for="my_name" class="form-label">名前</label>
        <input type="text" class="form-control" name="my_name" value="<?php if (!empty($_SESSION['name'])) {
                                                                        echo $_SESSION['name'];
                                                                      } ?>">
      </div>
      <div class="mb-3">
        <label for="my_age" class="form-label">年齢</label>
        <input type="number" class="form-control" name="my_age" value="<?php if (!empty($_SESSION['age'])) {
                                                                          echo $_SESSION['age'];
                                                                        } ?>">
      </div>
      <div>
        <label for="email" class="form-label">メールアドレス</label>
        <input type="text" class="form-control" name="email" value="<?php if (!empty($_SESSION['email'])) {
                                                                      echo $_SESSION['email'];
                                                                    } ?>">
      </div>
      <div class="mt-3">
        <input type="submit" class="btn btn-primary" value="データの送信">
      </div>
    </form>
  </div>
</body>

</html>

receive.php

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $name = htmlspecialchars($_POST['my_name'], ENT_QUOTES);
  $age = (int)$_POST['my_age'];
  $email = htmlspecialchars($_POST['email'], ENT_QUOTES);
  session_start();
  $_SESSION['name'] = $name;
  $_SESSION['age'] = $age;
  $_SESSION['email'] = $email;

  // name check
  if (empty($name)) {
    $error['name'] = '名前を入力してください';
    // name length check
    if(mb_strlen($name) > 20) {
      $error['name'] = '名前は20文字以内で入力してください';
    }
  }

  // age check
  if (empty($age)) {
    $error['age'] = '年齢を入力してください';
  } elseif ($age < 0 || $age > 120) {
    $error['age'] = '年齢は0以上120以下で入力してください';
  } elseif (!preg_match('/^[0-9]+$/', $age)) {
    $error['age'] = '年齢は半角数字で入力してください';
  }

  // email check
  if (empty($email)) {
    $error['email'] = 'メールアドレスを入力してください';
  } elseif (!preg_match('/^[a-zA-Z0-9.!#$%&\\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/', $email)) {
    $error['email'] = 'メールアドレスを正しく入力してください';
  }

}

// エラーがある場合前の画面へ戻す
if (isset($error)) {
  // エラーメッセージをセッションに保存
  $_SESSION['error'] = $error;
  header('Location: index.php');
  exit;
}

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

<?php include './common/head.php';?>

<body>
  <div class="container-sm mt-5">
    <h1>データ確認画面</h1>
    <form action="compleat.php" method="post">
      <input type="hidden" name="my=name" value="<?php echo $name?>">
    <input type="hidden" name="my=age" value="<?php echo $age?>">
    <table class="table">
      <tbody>
        <tr>
          <th scope="row">名前</th>
          <td><?php echo $name?></td>
        </tr>
        <tr>
          <th scope="row">年齢</th>
          <td><?php echo $age?></td>
        </tr>
        <tr>
          <th scope="row">メールアドレス</th>
          <td><?php echo $email?></td>
        </tr>
      </tbody>
    </table>
    <div class="mx-auto">
      <input type="submit" class="btn btn-primary" value="完了">
    </div>
  </form>
</div>
</body>

</html>

完了画面の表示

<?php
session_reset()
?>

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

<?php include './common/head.php'; ?>

<body>
  <div class="container-sm mt-5">
    <div class="alert alert-success" role="alert">
      <p class="mb-0">登録が完了しました。</p>
    </div>
    <a href="index.php" class="btn btn-secondary">TOPへ戻る</a>
  </div>
</body>

</html>

完了画面は、登録が完了したことがわかるようにメッセージを表示するだけになっています。

まとめ

今回はWebフォームの作成方法について学んで行きました。

Webフォームは初学者にとって良い練習になるので、一人で作れるようになっていて損はありません。

難しい部分も多かったかと思いますが、1つずつ整理しながら作って行きましょう。

フォームを作成する上で気をつけるポイント

  • XSS対策
  • ユーザーのチェック
  • データの整合性
  • ストレスのないフォーム

空前絶後の費用対効果!デザイン・プログラミングの習得なら【Web食いオンラインスクール】

Web系のオンラインスクールの中では、費用対効果がかなり高く、講師のほとんどが現役のフリーランス であるため生きた記述を学ぶことができます。

また、やめたいときにすぐに辞めることができるので、合わないと思ったときすぐに辞めることができます。

学べる内容や言語

  • Webデザイン
  • Webディレクション
  • Web系プログラミング

Webデザイン

  • Xd
  • Illustrator
  • Photoshop
  • UI・UXデザイン構築

Webディレクション

  • Google Analytics
  • SEO
  • サーチコンソール
  • ウーバーサジェスト

Web系プログラミング

  • HTML
  • CSS
  • Sass
  • Bootstrap
  • JavaScript
  • php
  • Laravel
  • MySQL
  • git
  • github
こんな人におすすめ!
  • 現実を見据えて学びたい方
  • 高品質な実績を持つWebデザイナーになりたい方
  • Web プログラマー・エンジニアになりたい方
  • 途中でコースを変更する可能性がある方
  • 現役のフリーランスから学びたい方

プログラミング
スポンサーリンク
スポンサーリンク
e-logsをフォローする
スポンサーリンク
eLogs

コメント

タイトルとURLをコピーしました