PHPでお問い合わせフォームを作る

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ PHPを使ってお問い合わせフォームを実装

学習したことを一気に書いていたら長文になってしまいました。それでも構わなければご覧下さい。

手軽にお問い合わせフォームを実装したいという方は以下の記事をご覧下さい。
・参考記事：[Googleフォームを使ってお問い合わせ機能を実装する](https://qiita.com/s79ns/items/6782f46f49e1be38a6ff)

## ローカルでPHPの動作確認をする

XAMPPやMAMPなどを使わずに、ローカル環境で動作確認をしたい場合は、phpがインストールされている状態で、以下のコマンドを開発ディレクトリ下で実行しWebサーバを起動します。

```terminal
php -S localhost:8888
```

[http://localhost:8888/](http://localhost:8888/)にアクセスをすると、index.phpの内容が表示されます。

![スクリーンショット 2021-02-09 10.35.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/05b8978e-c230-37e6-98dd-11038813bd23.png)

## 概要

処理の全体図を画面イメージとシーケンス図を使って解説します。

#### 画面イメージ

PHPを使って、以下のような入力・確認・完了の3つの画面で構成する
お問い合わせフォームを実装する方法をご紹介します。

![スクリーンショット 2021-01-29 15.15.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/6dbfca82-7739-3e85-ca9e-aea1d191e7b4.png)

① 名前・Eメール・メッセージを入力して確認ボタンを押下します。

② 入力した情報が表示される確認画面に移動し、送信ボタンを押下します。

③ 送信が完了した旨の画面が表示され、入力した情報が入力者と管理者にメールで届きます。



#### シーケンス図

こちらはブラウザとWebサーバ間の通信のやりとりを図で表したものです。

![スクリーンショット 2021-01-29 17.37.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/f7e210ee-9633-3892-4671-e20902f99ce5.png)


① ブラウザ側からcontactform.phpというファイルに入力画面の表示を要求します。

② Webサーバがブラウザに入力画面を返します。

③ 入力者が名前・Eメール・メッセージを入力し、確認ボタンを押下します。

④ Webサーバが入力された内容を確認させるため、確認画面を返します。

⑤ 入力者が内容を確認し、送信ボタンを押下します。

⑥ Webサーバが入力を受け付け、ブラウザに完了画面を返し、入力者と管理者にメールを送信します。

#### GETとPOST

サーバーへのリクエストは、**GET方式**と**POST方式**の2種類があります。
シーケンス図では、初回要求がGET方式で、2回目と3回目ではPOST方式でリクエストをしています。

GETは、普段Webブラウザからサーバへアクセスする方式です。
POSTは、ブラウザからサーバに情報を送る際に行うアクセス方式です。

初回要求では、単にサーバに入力画面の表示を要求しているだけなので**GET方式**です。
フォーム入力後の画面で、入力者は名前・Eメール・メッセージをサーバに送るため、
確認画面では入力した情報を確認し、サーバに情報を送りたいのでいずれも**POST方式**となります。

## HTML（入力画面）

お問い合わせフォームのHTMLの一例です。

```html
  <form action="./contactform.php" method="post">
    名前<input type="text" name="fullname" value="">
    Eメール <input type="email" name="email" value="">
    本文<textarea name="message" id="" cols="" rows=""></textarea>
    <input type="submit" name="confirm" value="確認" class="button">
  </form>
```

#### formタグ

formタグは入力フォームを作成し、このタグ内にフォームを構成する部品を配置します。
action属性は、送信先の指定をするもので、次の画面に行く時に呼び出すファイルを指定します。

今回は、1つのファイルで入力・確認・完了画面を処理しますので、./contactform.phpと指定します。
<font color="gray">※ 現在のファイルと次のアクションが同じなので、action属性は省略できますが、明示的に記述します。
※ ファイルパスが書き換わった場合に備え、ファイルパスは絶対パスではなく相対パスで記述します。</font>

methodは、次の画面に移動する際にデータを入力してサーバに送るのでpostを指定します。
<font color="gray">※methodの記述を省略すると、getでの送信となります。</font>

#### inputタグ

name属性は、inputタグにつける固有の名前です。何でも~~小学校の頃好きだった女子の名前で~~構いません。
Eメールのinput type="email"にすると、ブラウザが入力欄がEメールだと認識し、入力者がEメール以外の文字列を入力するとブラウザが警告してくれるようになります。もちろんinput type="text"でもOKです。

送信ボタンをinput type="submit"とすることで、送信するボタンを意味します。
valueに文字列を入力すると、そのままボタンの名前として表示されます。ここでは確認としました。

そうすると、CSSを少しいじっていますがこんな感じになります。

![スクリーンショット 2021-01-30 11.06.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/b9a513fa-4c6f-0eec-7de0-7cf89a74bf47.png)

## HTML（確認画面）

続いてHTMLの確認画面を作っていきます。

#### フロー図

GET方式かPOST方式によってPHPで条件分岐させ、入力画面か確認画面を出すか切り替えて表示します。

![スクリーンショット 2021-01-30 11.41.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/a8830e9f-b5e7-a924-2f31-60a83ce07495.png)

ひし形の部分は条件分岐で、ここでGETかPOSTかを判別します。
GETでは下に分岐して入力画面を表示し、POSTであれば右に分岐して確認画面を表示します。

#### POSTの判断はPHPでどう書けばいいのか

PHPに元々組み込まれている**スーパーグローバル変数**を使います。
**スーパーグローバル変数（$_POST）**に入力された値が入っているかでPOSTのアクセスかを判断します。

$_POSTは以下のような連想配列になっていて、画面で入力された値が配列として保管されています。
そのキー名を入力することで、対となる値を取得することができます。

| キー | 値 |
|:----|:---|
| $_POST["fullname"] | みなみ |
| $_POST["email"] | hoge@fuga,com |
| $_POST["message"] | こんにちは！ |
| $_POST["confirm"] | 確認 |

PHPで書くと以下の通りで、<?php?>タグで囲った部分がPHPの処理を書ける部分です。
PHPの処理を書く時は必ずこのタグで囲む必要があります。
POSTに情報がある時は、確認画面のHTMLを表示し、POSTに情報がなければ
入力画面を表示させる条件分岐となります。

```php

<?php if( $_POST ){ ?>
  POST情報があるときのHTMLコード（確認画面）
<?php } else { ?>
  POST情報がないときのHTMLコード（入力画面）
<?php } ?>
```

具体的に書くと、以下のようなコードとなります。
echoはPHPで画面に表示するためのものです。
また、本文のnl2brは、本文の中に改行が含まれている場合に、HTMLの改行タグに変換する関数です。

```php
<?php if($_POST ){ ?>
  <!-- 確認画面 -->
  <form action="./cotactform.php" method="post">
    名前 <?php echo $_POST["fullname"] ?>
    Eメール <?php echo $_POST["email"] ?>
    本文 <?php echo nl2br($_POST["message"]) ?>
    <input type="submit" name="back" value="戻る" />
    <input type="submit" name="send" value="送信" />
  </form>
<?php } else { ?>
  <!-- 入力画面 -->
  <form action="./contactform.php" method="post">
    名前 <input type="text" name="fullname" value="">
    Eメール <input type="email" name="email" value="">
    本文 <textarea name="message" id="" cols="" rows=""></textarea>
    <input type="submit" name="confirm" value="確認" class="button">
  </form>
<?php } ?>
```

## 画面遷移の制御

次に確認画面内にある『戻る』と『送信』ボタンの遷移についてです。

#### 追加フロー図

確認画面から『戻る』と『送信』ボタンを押下した際のフロー追加した図がこちらです。

![スクリーンショット 2021-01-31 11.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/86f5c3b9-8709-f894-1a5c-c420f42da680.png)

**入力画面はGETか$_POST["back"]で来る時の2つ**で、**確認画面は$_POST["confirm"]がある時**、
**完了画面は$_POST["send"]がある時**に条件分岐を行えば良いことになります。

#### 変数$modeで管理する

分かりやすくするために、ページ遷移についてinput,confirm,sendの3つのモードを作成し
これらを変数$modeで管理する方法をご紹介します。

![スクリーンショット 2021-01-31 13.07.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/1147c5d2-5206-0e21-501b-f4734d7175f0.png)

##### $modeの定義

実際のコードは以下の通りです。

```php:cotactform.php
<?php
  $mode = "input";
  if( isset($_POST["back"] ) && $_POST["back"] ){
    // 何もしない
  } else if( isset($_POST["confirm"] ) && $_POST["confirm"] ){
    $mode = "confirm";
  } else if( isset($_POST["send"] ) && $_POST["send"] ){
    $mode = "send";
?>
```

$modeという変数を定義して、初期状態をinput（入力画面）とします。

if( isset(POST["back"] ) && $_POST["back"] )の部分は、backという配列のキーが存在している且つ、POSTに値が入っているかを確認しています。
いきなり、POST["back"]で条件判定をしてもいいですが、"back"というキーが存在しない時に
このコードを通ると、PHPのシステムが異常を検知して警告を出します。
これを回避するために、そもそも"back"というキーが存在しているということを確認しています。
この条件式に当てはまると入力画面になりますが、初期値はinputなのでここで処理は何も行いません。

＄modeがいずれかの値になるように判定式を作ることで、$modeは"input"、"confirm"、"send"のいずれかとなります。

##### HTMLの編集

上で定義した$_modeを使うために編集します。

```php
<?php if( $mode == "input" ){ ?>
  <!-- 入力画面 -->
  <form action="./contactform.php" method="post">
    名前 <input type="text" name="fullname" value="">
    Eメール <input type="email" name="email" value="">
    本文 <textarea name="message" id="" cols="" rows=""></textarea>
    <input type="submit" name="confirm" value="確認" class="button">
  </form>
<?php } else if( $mode == "confirm" ){ ?>
  <!-- 確認画面 -->
  <form action="./cotactform.php" method="post">
    名前 <?php echo $_POST["fullname"] ?>
    Eメール <?php echo $_POST["email"] ?>
    本文 <?php echo nl2br($_POST["message"]) ?>
    <input type="submit" name="back" value="戻る" />
    <input type="submit" name="send" value="送信" />
  </form>
<?php } else { ?>
  <!-- 完了画面 -->
<?php } ?>
```

if( $mode == "input" )はmodeがinputであった時で、==は等しいを意味します。
これをそれぞれ確認画面と完了画面で条件分岐していきます。

## セッション

現状では確認画面にて『戻る』を押下すると、入力した内容が消えて、入力画面に戻ってきてしまいます。

![セッションがない.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/1b55f20c-cccd-c63f-6682-e9a14e1e163b.gif)

これには入力したデータをサーバに保存して、どの画面でも使えるようにしなければいけません。

サーバにデータを保存する仕組みを**セッション**といいます。
セッションでデータを保存するタイミングは、フォームに入力して『確認』を押下した時です。

```
session_start()　・・・　セッションを使うために必須で、セッションの開始を表します

$_SESSION = 値　・・・　セッションに値を保存する（配列もOK）

$_SESSION = array() ・・・　セッション情報をクリア（初期化する）
```

#### $modeの編集

```php:cotactform.php
<?php
  session_start();
  $mode = "input";
  if( isset($_POST["back"] ) && $_POST["back"] ){
    // 何もしない
  } else if( isset($_POST["confirm"] ) && $_POST["confirm"] ){
    $_SESSION["fullname"] = $_POST["fullname"];
    $_SESSION["email"] = $_POST["email"];
    $_SESSION["message"] = $_POST["message"];
    $mode = "confirm";
  } else if( isset($_POST["send"] ) && $_POST["send"] ){
    $mode = "send";
  } else {
    $SESSION = array();
  }
?>
```

処理の先頭で、セッションを使う宣言を行い、$_POSTの"fullname"、"email"、"message"をそれぞれ
SESSIONに代入することで、3つの値をセッションに保存することができます。

if文の最後にelseを作って、GETで来た時用にセッションを初期化するコードを入力します。

#### 入力画面と確認画面の編集

続いて入力画面と確認画面の編集を行います。
まず、下記のように入力画面の名前のvalueにセッション値を入れるコードを書きます。

```php
名前 <input type="text" name="fullname" value="<?php echo $_SESSION["fullname"] ?>">
```

これで名前の入力欄に値がセットされるようになります。
次に、確認画面を下記のように編集します。

```php
名前 <?php echo $_SESSION["fullname"] ?>
```

以前は$_POSTの値を表示させていましたが、SESSIONの値を使います。
同様にEメールと本文を編集すると、以下のようになります。
<font color="gray">※ 本文ですが、textareaタグにvalue属性は存在しませんので、記述する場所には注意が必要です。</font>

```php
<?php if( $mode == "input" ){ ?>
  <!-- 入力画面 -->
  <form action="./contactform.php" method="post">
    名前 <input type="text" name="fullname" value="<?php echo $_SESSION["fullname"] ?>">
    Eメール <input type="email" name="email" value="<?php echo $_SESSION["email"] ?>">
    本文 <textarea name="message"><?php echo $_SESSION["message"] ?></textarea>
    <input type="submit" name="confirm" value="確認" class="button">
  </form>
<?php } else if( $mode == "confirm" ){ ?>
  <!-- 確認画面 -->
  <form action="./cotactform.php" method="post">
    名前 <?php echo $_SESSION["fullname"] ?>
    Eメール <?php echo $_SESSION["email"] ?>
    本文 <?php echo nl2br($_SESSION["message"]) ?>
    <input type="submit" name="back" value="戻る" />
    <input type="submit" name="send" value="送信" />
  </form>
<?php } else { ?>
  <!-- 完了画面 -->
<?php } ?>
```

これで入力した内容が保存され、戻るボタンを押下しても情報が保存されるようになりました。

![セッションが保存される.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/47f3b5f2-a232-84c7-58b7-fb03abe067d0.gif)

#### セッションの特徴や注意点

セッションの特徴や注意点として、セッションはユーザー・ブラウザごとに保存されます。
自分が入力した内容は、他の人のブラウザでは表示されませんし、同じ人がchromeで入力した内容は
firefoxで表示されません。
また、セッションで入力した内容は、サーバの中に保存されます。送信画面でお問い合わせフォームの役割を終えた時は、セキュリティ観点のため、セッションの内容をクリアしておきましょう。
**セッションを使う場面とクリアする場面を意識することが重要です。**

## メールの送信

次に、メールが正しく送信できるかmail関数を使って確認します。
mail.phpファイルを以下の内容で新規作成し、サーバにファイルをアップしてブラウザで読み込んで下さい。
ブラウザには何も表示されませんが、成功すればメールが送信されます。

```php:mail.php
<?php
  mail("hoge@fuga.com", "表題subject", "本文の内容\r\n次の行");
?>
```

1つ目は宛先のメールアドレス、続いて件名、最後に本文の内容です。
<font color="gray">※ \rは改行で、シングルクォーテーションで囲むと機能しません。
※ 日本語が文字化けしていないかの確認も含め、件名と本文に日本語と英語を混ぜると尚良いです。</font>

メールを送信して文字化けが発生した場合は、mb_send_mail関数というものを使います。

```php:mail.php
<?php
  mb_language("ja");
  mb_internal_encording("UTF-8");
  mb_send_mail("hoge@fuga.com", "表題subject", "本文の内容\r\n次の行");
?>
```

## HTML（送信画面）

送信が完了した場合の処理を記述します。

```php:cotactform.php
  } else if( isset($_POST["send"] ) && $_POST["send"] ){
    $message = "お問い合わせを受け付けました\r\n"
             . "名前" . $_SESSION["fullname"] . "\r\n"
             . "email" . $_SESSION["email"] . "\r\n"
             . "お問い合わせ内容:\r\n"
             . preg_replace("/\r\n|\r|\n/", "\r\n", $_SESSION["message"] );
    mail($_SESSION["email"], "お問い合わせありがとうございます", $message );
    mail("hoge@fuga.com", "お問い合わせありがとうございます", $message );
    $_SESSION = array();
    $mode = "send";
  }
```
２〜6行目は、変数messageの内容で、まとめて1つの処理ですので、セミコロンは最後の行のみでOKです。
ピリオドは文字列を結合するための記号です。
preg_replace()関数は、改行のコードを揃えるために使うもので、\r\n\、\r、\nをそれぞれ全て\r\nに変換しています。
7行目は、入力者にmail関数でメールを送っています。入力者のemailアドレスは
SESSION["email"]に入っているので、それを宛先にしています。変数$messageはメール本文の内容です。
8行目は、管理者宛てにmail関数でメールを送っています。

## HTML（完了画面）

送信が完了した場合の画面を記述します。

```php
<?php } else { ?>
  <!-- 完了画面 -->
  送信しました。お問い合わせありがとうございました。
<?php } ?>
```

ここまでのコードがこちらです。

```php:cotactform.php
<?php
  session_start();
  $mode = "input";
  if( isset($_POST["back"] ) && $_POST["back"] ){
    // 何もしない
  } else if( isset($_POST["confirm"] ) && $_POST["confirm"] ){
    $_SESSION["fullname"] = $_POST["fullname"];
    $_SESSION["email"] = $_POST["email"];
    $_SESSION["message"] = $_POST["message"];
    $mode = "confirm";
  } else if( isset($_POST["send"] ) && $_POST["send"] ){
    // 送信ボタンを押下
    $message = "お問い合わせを受け付けました\r\n"
             . "名前" . $_SESSION["fullname"] . "\r\n"
             . "email" . $_SESSION["email"] . "\r\n"
             . "お問い合わせ内容:\r\n"
             . preg_replace("/\r\n|\r|\n/", "\r\n", $_SESSION["message"] );
    mail($_SESSION["email"], "お問い合わせありがとうございます", $message );
    mail("hoge@fuga.com", "お問い合わせありがとうございます", $message );
    $_SESSION = array();
    $mode = "send";
  } else {
    $SESSION = array();
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
<body>
  <?php if( $mode == "input" ){ ?>
    <!-- 入力画面 -->
    <form action="./contactform.php" method="post">
      名前 <input type="text" name="fullname" value="<?php echo $_SESSION["fullname"] ?>">
      Eメール <input type="email" name="email" value="<?php echo $_SESSION["email"] ?>">
      本文 <textarea name="message" id="" cols="" rows="" value="<?php echo $_SESSION["message"] ?>"></textarea>
      <input type="submit" name="confirm" value="確認" class="button">
    </form>
  <?php } else if( $mode == "confirm" ){ ?>
    <!-- 確認画面 -->
    <form action="./cotactform.php" method="post">
      名前 <?php echo $_SESSION["fullname"] ?>
      Eメール <?php echo $_SESSION["email"] ?>
      本文 <?php echo nl2br($_SESSION["message"]) ?>
      <input type="submit" name="back" value="戻る" />
      <input type="submit" name="send" value="送信" />
    </form>
  <?php } else { ?>
    <!-- 完了画面 -->
    送信しました。お問い合わせありがとうございました。
  <?php } ?>
</body>
</html>
```

## 入力画面での入力チェック

フォームとしての形は大分完成しましたが、現状入力画面で名前、Eメール、本文欄に何も入力されていない状態でも確認画面に遷移してしまい、メールを送信することができません。
入力画面で名前、email、本文が入力されているかチェックを行うよう処理を追加します。

![スクリーンショット 2021-01-31 11.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/39fb517f-3a25-1d71-ae43-be9a9584ae06.png)

各入力項目を以下のように設計します。このようなチェックを**バリデーション（検証）**といいます。

| 入力欄 | チェック内容 |
|:------|:----------|
| 名前 | 入力必須、100文字以内 |
| email | 入力必須、200文字以内、Eメール形式 |
| 本文 | 入力必須、500文字以内 |

## セキュリティ対策

お問い合わせフォームは誰でも入力できる画面なので、あらゆる攻撃を受ける可能性があります。
例えば、不正なプログラムコードを名前欄に入れられてしまった場合、ブラウザの中に含まれる個人情報が表示されてしまいます。
このように不正なコードを入れられる攻撃を**クロスサイトスクリプティング攻撃（XSS）**といいます。
ですので、お問い合わせフォームを作成する際は、XSS攻撃の対策をする必要があります。

XSS攻撃を防ぐためには、プログラムとして解釈される特殊文字を害のない文字に変換（無害化）します。
これを**サニタイズ**といいます。

| 特殊文字 | 無害化されたコード |
|:------:|:--------------:|
| &（アンパサンド） | \&amp; |
| "（ダブルクォート） | \&quot; |
| '（シングルクォート） | \&#039; |
| <（小なり） | \&lt; |
| >（大なり） | \&gt; |

特殊文字を無害化されたコードに変換をしても、ブラウザ上では特殊文字として表示されますが
プログラムとして実行されるコードにはなりません。

何も入力されずに送信されるかもしれない、想定外の文字数でメッセージが送られてくるかもしれない、Eメール以外の文字列で入力されるかもしれない、XSS攻撃を受けるかもしれない...
**どんな値で入力されるのか事前に想定しておくことが重要です。**

## バリデーションとサニタイズ導入

では、バリデーションとサニタイズ処理の追加をしていきます。

#### 名前入力欄

```php
  session_start();
  $mode = "input";
  $errmessage = array();
  if( isset($_POST["back"]) && $_POST["back"] ){
    // 何もしない
  } else if( isset($_POST["confirm"]) && $_POST["confirm"] ){
    if( !$_POST["fullname"] ){
      $errmessage[]= "名前を入力して下さい";
    } else if ( mb_strlen($_POST["fullname"]) > 100 ){
      $errmessage[]= "名前は100文字以内にして下さい";
    } 
    $_SESSION["fullname"] = htmlspecialchars($_POST["fullname"], ENT_QUOTES);
```

7行目で$_POST["fullname"]に値がなければfalseになり、!でfalse→trueに反転し、エラーメッセージ「名前を入力して下さい」が表示され、エラーメッセージ文字列を変数errmessageに保存します。

errmessageは3行目で初期化し、キーが無い配列[]に値を代入すると、配列の最後に値が保存されます。
従って、名前入力欄が空の時は「名前を入力して下さい」のエラーメッセージを表示します。

名前入力欄が空ではない時は、phpの標準関数mb_strlen()で引数($_POST["fullname"])の文字数をチェックし、100文字以上であれば「名前は100文字以内にして下さい」のエラーメッセージを表示します。

最後の2行は、JavaScriptの記号を無害化してくれる関数です。
$_POST["fullname"]の値をこの関数を介して、変換された文字列をSESSION["fullname"]に入れています。

#### Eメール欄

Eメールアドレス欄は、メールアドレスの形式になっているかの確認を行います。
その際は、filter_var()関数を使います。尚、この関数はURL形式かの判別にも用いることができます。

filter_var関数は、メールアドレスの形式であった場合はtrueを返します。
今回は、Eメール形式でなかった際に条件式の中に入ってきて欲しいので、否定の意味で!を使います。

```php
    if( !$_POST["email"] ){
      $errmessage[] = "Eメールを入力して下さい";
    } else if( mb_strlen($_POST["email"]) ) > 200 ){
      $errmessage[] = "Eメールは200文字以内にして下さい";
    } else if( !filter_var($_POST["email"], FILTER_VALIDETE_EMAIL) ){
      $errmessage[] = "メールアドレスが不正です";
    }
    $_SESSION["email"] = htmlspecialchars($POST["email"], ENT_QUOTES); 
```

#### 本文欄

本文欄も他項目と同じ要領で記述していきます。

```php
  if ( !$_POST["message"] ){
    $errmessage[] = "お問い合わせ内容を入力して下さい";
  } else if( mb_strlen($_POST["message"]) > 500 ){
    $errmessage = "お問い合わせ内容は500文字以内にして下さい";
  }
  $_SESSION["message"] = htmlspecialchars($_POST["message"], ENT_QUOTES);
```

#### エラー表示の追加（HTML）

エラーが発生した際に表示する内容をHTML側に記述していきます。

```php
  <?php if( $mode == "input" ){ ?>
    <!-- 入力画面 -->
    <?php
    if( $errmessage ){
      echo '<div class="alert alert-danger" role="alert">';
      echo implode('<br>', $errmessage );
      echo '</div>';
    }
    ?>
```

もし$message配列に値が1つでもあれば、if文の分岐の中に入り、何もなければ判定がfalseとなりますので
処理が行われません。
そしてmessageは配列ですので、これをそのまま表示することができません。
そこで、配列の各要素を文字列として連結して出すために**implode()関数**を使い、配列のそれぞれの要素を連結する際にbrタグを要素間につけて文字列をつなげることで、配列の要素を行ごとに表示することができます。

## まとめ

これでお問い合わせフォームの機能として完成しました。

```php:cotactform.php
<?php
  session_start();
  $mode = 'input';
  $errmessage = array();
  if( isset($_POST['back']) && $_POST['back'] ){
    // 何もしない
  } else if( isset($_POST['confirm']) && $_POST['confirm'] ){
	  // 確認画面
    if( !$_POST['fullname'] ) {
	    $errmessage[] = "名前を入力してください";
    } else if( mb_strlen($_POST['fullname']) > 100 ){
	    $errmessage[] = "名前は100文字以内にしてください";
    }
	  $_SESSION['fullname']	= htmlspecialchars($_POST['fullname'], ENT_QUOTES);

	  if( !$_POST['email'] ) {
		  $errmessage[] = "Eメールを入力してください";
	  } else if( mb_strlen($_POST['email']) > 200 ){
		  $errmessage[] = "Eメールは200文字以内にしてください";
    } else if( !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) ){
	    $errmessage[] = "メールアドレスが不正です";
	  }
	  $_SESSION['email']	= htmlspecialchars($_POST['email'], ENT_QUOTES);

	  if( !$_POST['message'] ){
		  $errmessage[] = "お問い合わせ内容を入力してください";
	  } else if( mb_strlen($_POST['message']) > 500 ){
		  $errmessage[] = "お問い合わせ内容は500文字以内にしてください";
	  }
	  $_SESSION['message'] = htmlspecialchars($_POST['message'], ENT_QUOTES);

	  if( $errmessage ){
	    $mode = 'input';
    } else {
	    $mode = 'confirm';
    }
  } else if( isset($_POST['send']) && $_POST['send'] ){
    // 送信ボタンを押したとき
    $message  = "お問い合わせを受け付けました \r\n"
              . "名前: " . $_SESSION['fullname'] . "\r\n"
              . "email: " . $_SESSION['email'] . "\r\n"
              . "お問い合わせ内容:\r\n"
              . preg_replace("/\r\n|\r|\n/", "\r\n", $_SESSION['message']);
	  mail($_SESSION['email'],'お問い合わせありがとうございます',$message);
    mail('fuga@hogehoge.com','お問い合わせありがとうございます',$message);
    $_SESSION = array();
    $mode = 'send';
  } else {
    $_SESSION['fullname'] = "";
    $_SESSION['email']    = "";
    $_SESSION['message']  = "";
  }
?>
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>お問い合わせフォーム</title>
</head>
<body>
  <?php if( $mode == 'input' ){ ?>
    <!-- 入力画面 -->
    <?php
      if( $errmessage ){
        echo '<div style="color:red;">';
        echo implode('<br>', $errmessage );
        echo '</div>';
      }
    ?>
    <form action="./contactform.php" method="post">
      名前    <input type="text"    name="fullname" value="<?php echo $_SESSION['fullname'] ?>"><br>
      Eメール <input type="email"   name="email"    value="<?php echo $_SESSION['email'] ?>"><br>
      お問い合わせ内容<br>
      <textarea cols="40" rows="8" name="message"><?php echo $_SESSION['message'] ?></textarea><br>
      <input type="submit" name="confirm" value="確認" />
    </form>
  <?php } else if( $mode == 'confirm' ){ ?>
    <!-- 確認画面 -->
    <form action="./contactform.php" method="post">
      名前    <?php echo $_SESSION['fullname'] ?><br>
      Eメール <?php echo $_SESSION['email'] ?><br>
      お問い合わせ内容<br>
      <?php echo nl2br($_SESSION['message']) ?><br>
      <input type="submit" name="back" value="戻る" />
      <input type="submit" name="send" value="送信" />
    </form>
  <?php } else { ?>
    <!-- 完了画面 -->
    送信しました。お問い合わせありがとうございました。<br>
  <?php } ?>
</body>
</html>
```

## 関連記事

[PHPでお問い合わせフォームを作る：CSRF対策](https://qiita.com/s79ns/items/87b9849e23a87ea4b17f)