一般的にWebサイト構築の仕事はWebデザイナー / コーダー / フロントエンド / バックエンドと分野別に分かれることがあり、Webサイト上のフォームの実装はWebデザイナーの仕事に含まれないかもしれません。
しかし小規模な制作会社やチームでは他職種の仕事を兼業することもしばしば。
今回のPHPで動くWebフォームの実装などは代表的な例と言えるでしょう。
「外部のフォーム作成サービスは使わずに、Webフォーム作ってもらえますか?」と言われた際、ヒィヒィ言いながら情報検索とやっつけ仕事になるより、サクッと対応できると良いですよね。
そこで今回はWebデザイナーさんに向けて、何回も使い回せる「PHP Mailerを使ったWebフォームテンプレート」をご紹介したいと思います。同じような状況でお困りのWebデザイナーさんは是非参考にしてみてくださいね。
一部、このブログの過去の記事と被る箇所があります。
興味のある方は下記の記事も参考にしてみてくださいね。
この記事で学べること
- 入力画面 / 確認画面 / 完了画面の3構成
- バリデーション(※入力間違い防止のため)
- 通常の入力欄の他、ラジオボタン・チェックボックス・セレクトボックスに対応
- PHP Mailerを利用して、SMTPでメールを送信
- Google reCAPTCHAで不正アクセス・送信を防止
- 入力画面でエラーがあった場合、バリデーションを表示
- cssでフォームのスタイルを調整
全体の構成
1つのディレクトリにすべてのファイルを入れるだけで動作します。
└── root
├── css
│ |── base.css
│ └── style.css
├── PHPMailer
│ |── PHPMailer
│ └── ...
├── index.php
├── confirm.php
└── complete.php
とりあえずコードです
①入力画面(index.php)
<!DOCTYPE html>
<html lang="ja">
<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>問い合わせフォーム</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/style.css">
<script src="js/common.js"></script>
<script src="https://www.google.com/recaptcha/api.js?render=リキャプチャのキー"></script>
</head>
<body id="body">
<section class="title">
<h1>問い合わせフォーム テンプレート</h1>
</section>
<section class="common">
<h2>問い合わせ入力画面</h2>
<form id="form" action="confirm.php" method="POST">
<input type='hidden' name='modeTo' value="confirm">
<p class="submitError"></p>
<div class="formRow col2">
<div class="formRowChild col2">
<label for="lastname"><span class="require">必須</span>性</label>
<input type="text" name="lastname" id="lastname" placeholder="例)山田" value="">
<p class="err-msg-last_name"></p>
</div>
<div class="formRowChild col2">
<label for="firstname"><span class="require">必須</span>名</label>
<input type="text" name="firstname" id="firstname" placeholder="例)太郎" value="">
<p class="err-msg-first_name"></p>
</div>
</div>
<div class="formRow col2">
<div class="formRowChild col2">
<label for="lastname_kana"><span class="require">必須</span>性(カタカナ)</label>
<input type="text" name="lastname_kana" id="lastname_kana" placeholder="例)ヤマダ" value="">
<p class="err-msg-last_name_kana"></p>
</div>
<div class="formRowChild col2">
<label for="firstname_kana"><span class="require">必須</span>名(カタカナ)</label>
<input type="text" name="firstname_kana" id="firstname_kana" placeholder="例)タロウ" value="">
<p class="err-msg-first_name_kana"></p>
</div>
</div>
<div class="formRow">
<label for="email"><span class="require">必須</span>メールアドレス</label>
<input type="text" name="email" id="email" placeholder="例)example@mail.com" value="">
<p class="err-msg-mail"></p>
</div>
<div class="formRow">
<label for="tel"><span class="require">必須</span>電話番号</label>
<input type="text" name="tel" id="tel" placeholder="例)06-1234-5678">
<p class="err-msg-tel"></p>
</div>
<div class="formRow">
<label for="sex"><span class="require">必須</span>性別</label>
<span class="radioCheck">
<input type="radio" name="sex" id="male" value="男性" checked>
<label for="male">男性</label>
</span>
<span class="radioCheck">
<input type="radio" name="sex" value="女性">
<label for="female">女性</label>
</span>
</div>
<div class="formRow">
<label for="inquiry"><span class="require">必須</span>お問い合わせ内容</label>
<select name="inquiry" id="inquiry">
<option value="">お問い合わせ内容を選択してください</option>
<option value="ご質問・お問い合わせ">ご質問・お問い合わせ</option>
<option value="ご意見・ご感想">ご意見・ご感想</option>
</select>
<p class="err-msg-inquiry"></p>
</div>
<div class="formRow">
<label for="contact_method"><span class="any">任意</span>ご希望の連絡方法</label>
<label class="radioCheck"><input type="checkbox" name="contact_method[]" value="電話" checked>電話</label>
<label class="radioCheck"><input type="checkbox" name="contact_method[]" value="メール">メール</label>
<label class="radioCheck"><input type="checkbox" name="contact_method[]" value="どちらでもよい">どちらでもよい</label>
</div>
<div class="formRow">
<label for="textarea"><span class="require">必須</span>メッセージ本文</label>
<textarea id="textarea" name="textarea" rows="5" placeholder="お問い合わせ内容を入力してください。"></textarea>
<p class="err-msg-textarea"></p>
</div>
<div class="formRow">
<button class="g-recaptcha" data-sitekey="リキャプチャのキー" data-action='submit' type="submit" id="submitButton">確認画面へ</button>
</div>
</form>
</section>
<script>
// バリデーション + リキャプチャ
window.addEventListener('DOMContentLoaded', () => {
const submits = document.querySelector('#submitButton');
submits.addEventListener('click', (e) => {
grecaptcha.ready(function () {
grecaptcha.execute('リキャプチャのキー', { action: 'submit' }).then(function (token) {
e.preventDefault();
// 姓名のチェック
const last_name = document.querySelector('#lastname');
const first_name = document.querySelector('#firstname');
const last_name_kana = document.querySelector('#lastname_kana');
const first_name_kana = document.querySelector('#firstname_kana');
// エラーメッセージを表示させる要素を取得
const errMsglast_name = document.querySelector('.err-msg-last_name');
const errMsgfirst_name = document.querySelector('.err-msg-first_name');
const errMsglast_name_kana = document.querySelector('.err-msg-last_name_kana');
const errMsgfirst_name_kana = document.querySelector('.err-msg-first_name_kana');
if (!last_name.value) {
errMsglast_name.classList.add('form-invalid');
errMsglast_name.textContent = '姓を入力してください';
} else {
errMsglast_name.textContent = '';
last_name.classList.remove('input-invalid');
errMsglast_name.classList.remove('form-invalid');
}
if (!first_name.value) {
errMsgfirst_name.classList.add('form-invalid');
errMsgfirst_name.textContent = '名を入力してください';
} else {
errMsgfirst_name.textContent = '';
first_name.classList.remove('input-invalid');
errMsgfirst_name.classList.remove('form-invalid');
}
if (!last_name_kana.value) {
errMsglast_name_kana.classList.add('form-invalid');
errMsglast_name_kana.textContent = '姓(カタカナ)を入力してください';
} else {
errMsglast_name_kana.textContent = '';
last_name_kana.classList.remove('input-invalid');
errMsglast_name_kana.classList.remove('form-invalid');
}
if (!first_name_kana.value) {
errMsgfirst_name_kana.classList.add('form-invalid');
errMsgfirst_name_kana.textContent = '名(カタカナ)を入力してください';
} else {
errMsgfirst_name_kana.textContent = '';
first_name_kana.classList.remove('input-invalid');
errMsgfirst_name_kana.classList.remove('form-invalid');
}
// メールアドレスのチェック
const mail = document.querySelector('#email');
const errMsgMail = document.querySelector('.err-msg-mail');
if (!mail.value.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/)) {
errMsgMail.classList.add('form-invalid');
errMsgMail.textContent = '正しいメールアドレスを入力してください';
mail.classList.add('input-invalid');
} else {
errMsgMail.textContent = '';
mail.classList.remove('input-invalid');
errMsgMail.classList.remove('form-invalid');
}
// 電話番号のチェック
const tel = document.querySelector('#tel');
const errMsgTel = document.querySelector('.err-msg-tel');
if (!tel.value.match(/^\(?\d{2,5}\)?[-(\.\s]{0,2}\d{1,4}[-)\.\s]{0,2}\d{3,4}$/)) {
errMsgTel.classList.add('form-invalid');
errMsgTel.textContent = '正しい電話番号を入力してください';
tel.classList.add('input-invalid');
} else {
errMsgTel.textContent = '';
tel.classList.remove('input-invalid');
errMsgTel.classList.remove('form-invalid');
}
// セレクトボックスのチェック
const inquiry = document.querySelector('#inquiry');
const errMsgInquiry = document.querySelector('.err-msg-inquiry');
if (!inquiry.value) {
errMsgInquiry.classList.add('form-invalid');
errMsgInquiry.textContent = '選択してください';
} else {
errMsgInquiry.textContent = '';
inquiry.classList.remove('input-invalid');
errMsgInquiry.classList.remove('form-invalid');
}
// テキストエリアのチェック
const textarea = document.querySelector('#textarea');
const errMsgTextarea= document.querySelector('.err-msg-textarea');
if (!textarea.value) {
errMsgTextarea.classList.add('form-invalid');
errMsgTextarea.textContent = '本文を入力してください';
} else {
errMsgTextarea.textContent = '';
textarea.classList.remove('input-invalid');
errMsgTextarea.classList.remove('form-invalid');
}
// フォーム上部にエラーメッセージを表示
const errMsgSubmit = document.querySelector('.submitError');
// フォームトップの高さを取得
const formPosition = document.querySelector('#form');
const errorElemOffsetTop = formPosition.offsetTop;
// フォーム上部にエラーメッセージを表示
if ((!tel.value.match(/^\(?\d{2,5}\)?[-(\.\s]{0,2}\d{1,4}[-)\.\s]{0,2}\d{3,4}$/)) || (!mail.value.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/)) || (!last_name.value) || (!first_name.value)|| (!last_name_kana.value) || (!first_name_kana.value) ||(!last_name_kana.value)||(!first_name_kana.value)||(!inquiry.value)||(!textarea.value)) {
errMsgSubmit.classList.add('form-invalid');
errMsgSubmit.textContent = '入力内容に誤りがあります。ご確認の上、再度入力してください。';
// フォームの先頭へスクロールさせる
window.scrollTo({
top: errorElemOffsetTop - 40,
behavior: 'smooth'
});
} else {
errMsgSubmit.textContent = '';
errMsgSubmit.classList.remove('form-invalid');
const form = document.getElementById('form');
form.submit();
}
});
});
}, false);
}, false);
</script>
</body>
</html>
②確認画面(confirm.php)
<?php
session_start();
// PHPMailer 必要なファイルを読み込み
require('./PHPMailer/PHPMailer/src/PHPMailer.php');
require('./PHPMailer/PHPMailer/src/Exception.php');
require('./PHPMailer/PHPMailer/src/SMTP.php');
// 送信ボタンを押したら
if (isset($_POST['modeTo'])) {
if ($_POST['modeTo'] === 'confirm') {
$firstname = $_POST["firstname"];
$lastname = $_POST["lastname"];
$firstname_kana = $_POST["firstname_kana"];
$lastname_kana = $_POST["firstname_kana"];
$tel = $_POST["tel"];
$email = $_POST["email"];
$sex = $_POST["sex"];
$inquiry = $_POST["inquiry"];
if (isset($_POST['contact_method']) && is_array($_POST['contact_method'])) {
$contact_method = implode("、", $_POST["contact_method"]);
}
$textarea = $_POST["textarea"];
$_SESSION["firstname"] = $_POST["firstname"];
$_SESSION["lastname"] = $_POST["lastname"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["tel"] = $_POST["tel"];
$_SESSION["email"] = $_POST["email"];
$_SESSION["sex"] = $_POST["sex"];
$_SESSION["inquiry"] = $_POST["inquiry"];
$_SESSION["contact_method"] = implode("、", $_POST["contact_method"]);
$_SESSION["textarea"] = $_POST["textarea"];
}
}
// 送信ボタンを押したら
if (isset($_POST['modeTo'])) {
if ($_POST['modeTo'] === 'send') {
$firstname = $_POST["firstname"];
$lastname = $_POST["lastname"];
$firstname_kana = $_POST["firstname_kana"];
$lastname_kana = $_POST["firstname_kana"];
$tel = $_POST["tel"];
$email = $_POST["email"];
$sex = $_POST["sex"];
$inquiry = $_POST["inquiry"];
$contact_method = $_POST["contact_method"];
$textarea = $_POST["textarea"];
$_SESSION["firstname"] = $_POST["firstname"];
$_SESSION["lastname"] = $_POST["lastname"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["tel"] = $_POST["tel"];
$_SESSION["email"] = $_POST["email"];
$_SESSION["sex"] = $_POST["sex"];
$_SESSION["inquiry"] = $_POST["inquiry"];
$_SESSION["contact_method"] = $_POST["contact_method"];
$_SESSION["textarea"] = $_POST["textarea"];
// 日本語エンコード
mb_language("uni");
mb_internal_encoding("UTF-8");
// インスタンス生成
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
// 文字エンコードを指定
$mail->CharSet = 'utf-8';
try {
// SMTPサーバの設定
$mail->isSMTP();
$mail->Host = 'SMTPサーバーを指定';
$mail->SMTPAuth = true;
$mail->Username = 'ユーザー名';
$mail->Password = 'パスワード'; // SMTPサーバーのパスワード
$mail->SMTPSecure = 'tls'; // 暗号化を有効(tls or ssl)無効の場合はfalse
$mail->Port = 587; // TCPポートを指定(tlsの場合は465や587)
// 送受信先設定(第二引数は省略可)
$mail->setFrom('送信元メールアドレス', '送信者名'); // 送信者
$mail->addAddress($email); // 宛先
$mail->addAddress('送信先メールアドレス'); // 宛先2
$mail->Sender = '送信できなかった場合の返送先'; // Return-path
// 送信内容設定
$mail->Subject = '[自動送信]お問い合わせ内容の確認';
$mail->Body =<<<EOM
{$lastname}{$firstname} 様
お問い合わせありがとうございます。
以下のお問い合わせ内容を、メールにて確認させていただきました。
===================================================
【 お名前 】
{$lastname}{$firstname}
【 フリガナ 】
{$lastname_kana}{$firstname_kana}
【 メール 】
{$email}
【 電話番号 】
{$tel}
【 性別 】
{$sex}
【 お問い合わせ内容 】
{$inquiry}
【 ご希望の連絡方法 】
{$contact_method}
【 メッセージ本文 】
{$textarea}
===================================================
内容を確認のうえ、回答させて頂きます。
しばらくお待ちください。
EOM;
// 送信
$mail->send();
header("Location: リダイレクト先のURLを記載");
} catch (Exception $e) {
// エラーの場合
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}}
$_SESSION = [];
session_destroy();
?>
<!DOCTYPE html>
<html lang="ja">
<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>問い合わせ確認画面</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/style.css">
<script src="js/common.js"></script>
<script src="https://www.google.com/recaptcha/api.js?render=リキャプチャのキー"></script>
</head>
<body id="body">
<section class="title">
<h1>問い合わせフォーム テンプレート</h1>
</section>
<section class="common">
<h2>問い合わせ確認画面</h2>
<form id="form" action="confirm.php" method="POST" name="form">
<input type='hidden' name='modeTo' value="send">
<input id="firstname" type="hidden" name="firstname" value="<?php echo $firstname; ?>">
<input id="lastname" type="hidden" name="lastname" value="<?php echo $lastname; ?>">
<input id="firstname_kana" type="hidden" name="firstname_kana" value="<?php echo $firstname_kana; ?>">
<input id="lastname_kana" type="hidden" name="lastname_kana" value="<?php echo $lastname_kana; ?>">
<input id="email" type="hidden" name="email" value="<?php echo $email; ?>">
<input id="tel" type="hidden" name="tel" value="<?php echo $tel; ?>">
<input id="sex" type="hidden" name="sex" value="<?php echo $sex; ?>">
<input id="inquiry" type="hidden" name="inquiry" value="<?php echo $inquiry; ?>">
<input id="contact_method" type="hidden" name="contact_method" value="<?php echo $contact_method; ?>">
<input id="textarea" type="hidden" name="textarea" value="<?php echo $textarea; ?>">
<div class="formRow col2">
<div class="formRowChild col2">
<label for="lastname"><span class="require">必須</span>性</label>
<p class="confirmText"><?php echo $lastname; ?></p>
</div>
<div class="formRowChild col2">
<label for="firstname"><span class="require">必須</span>名</label>
<p class="confirmText"><?php echo $firstname; ?></p>
</div>
</div>
<div class="formRow col2">
<div class="formRowChild col2">
<label for="lastname_kana"><span class="require">必須</span>性(カタカナ)</label>
<p class="confirmText"><?php echo $lastname_kana; ?></p>
</div>
<div class="formRowChild col2">
<label for="firstname_kana"><span class="require">必須</span>名(カタカナ)</label>
<p class="confirmText"><?php echo $firstname_kana; ?></p>
</div>
</div>
<div class="formRow">
<label for="email"><span class="require">必須</span>メールアドレス</label>
<p class="confirmText"><?php echo $email; ?></p>
</div>
<div class="formRow">
<label for="tel"><span class="require">必須</span>電話番号</label>
<p class="confirmText"><?php echo $tel; ?></p>
</div>
<div class="formRow">
<label for="sex"><span class="require">必須</span>性別</label>
<p class="confirmText"><?php echo $sex; ?></p>
</div>
<div class="formRow">
<label for="inquiry"><span class="require">必須</span>お問い合わせ内容</label>
<p class="confirmText"><?php echo $inquiry; ?></p>
</div>
<div class="formRow">
<label for="contact_method"><span class="require">必須</span>ご希望の連絡方法</label>
<p class="confirmText"><?php echo $contact_method; ?></p>
</div>
<div class="formRow">
<label for="textarea"><span class="require">必須</span>メッセージ本文</label>
<p class="confirmText"><?php echo $textarea; ?></p>
</div>
<div class="formRow col2 send">
<button type="button" value="内容を修正する" onclick="history.back()" id="backButton">内容を修正する</button>
<button class="g-recaptcha" data-sitekey="リキャプチャのキー" data-action='submit' type="submit" id="submitButton">送信する</button>
</div>
</form>
</section>
<script>
// バリデーション + リキャプチャ
window.addEventListener('DOMContentLoaded', () => {
const submits = document.querySelector('#submitButton');
submits.addEventListener('click', (e) => {
grecaptcha.ready(function () {
grecaptcha.execute('リキャプチャのキー', { action: 'submit' }).then(function (token) {
e.preventDefault();
// 姓名のチェック
const last_name = document.querySelector('#lastname');
const first_name = document.querySelector('#firstname');
const last_name_kana = document.querySelector('#lastname_kana');
const first_name_kana = document.querySelector('#firstname_kana');
// メールアドレスのチェック
const mail = document.querySelector('#email');
// 電話番号のチェック
const tel = document.querySelector('#tel');
// セレクトボックスのチェック
const inquiry = document.querySelector('#inquiry');
// テキストエリアのチェック
const textarea = document.querySelector('#textarea');
// フォーム上部にエラーメッセージを表示
const errMsgSubmit = document.querySelector('.submitError');
// フォームトップの高さを取得
const formPosition = document.querySelector('#form');
const errorElemOffsetTop = formPosition.offsetTop;
// フォーム上部にエラーメッセージを表示
if ((!tel.value.match(/^\(?\d{2,5}\)?[-(\.\s]{0,2}\d{1,4}[-)\.\s]{0,2}\d{3,4}$/)) || (!mail.value.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/)) || (!last_name.value) || (!first_name.value)|| (!last_name_kana.value) || (!first_name_kana.value) ||(!last_name_kana.value)||(!first_name_kana.value)||(!inquiry.value)||(!textarea.value)) {
} else {
const form = document.getElementById('form');
form.submit();
}
});
});
}, false);
}, false);
</script>
</body>
</html>
③完了画面(complete.php)
<!DOCTYPE html>
<html lang="ja">
<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>問い合わせ完了画面</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/style.css">
<script src="js/common.js"></script>
</head>
<body id="body">
<section class="title">
<h1>問い合わせフォーム テンプレート</h1>
</section>
<section class="common">
<h2>問い合わせ完了画面</h2>
<p>送信が完了しました。</p>
</section>
</body>
</html>
④スタイルシート(style.css)
html{
font-size:62.5%;
font-family:'Noto Sans JP',"ヒラギノ角ゴ ProN W4","游ゴシック体", YuGothic, "游ゴシック", "Yu Gothic","メイリオ","Meiryo","MS Pゴシック","MS PGothic",Sans-Serif;
line-height:1.8;
-webkit-text-size-adjust:100%;
overflow-x: hidden;
}
body{
position:relative;
}
h1{
font-size:3rem;
font-weight:600;
}
h2{
font-size:2rem;
color:#fff;
background:#282828;
padding:1.4rem;
margin-bottom:1.6rem;
border-radius:.4rem;
}
p,a,li,td,th,div,figure,figcaption{
font-size:1.6rem;
font-weight:500;
line-height:1.6;
}
img{
max-width:100%;
vertical-align: bottom;
}
section.title{
width:100%;
height:20rem;
display:flex;
justify-content: center;
align-items: center;
background: linear-gradient(95deg, #F93678, #FE8B74);
padding:3.2rem 1.6rem;
}
section.title h1{
color:#fff;
text-align:center;
}
section.common{
width:80%;
max-width:84rem;
margin:0 auto;
padding:3.2rem 1.6rem;
}
.require{
padding: 0.4rem 0.8rem;
background: linear-gradient(95deg, #F93678, #FE8B74);
color: #fff;
border-radius: 0.4rem;
margin-right: 0.6rem;
}
.any{
padding: 0.4rem 0.8rem;
background: #333333;
color: #fff;
border-radius: 0.4rem;
margin-right: 0.6rem;
}
.formRow{
width:100%;
margin-bottom:3.2rem;
}
.formRow.col2{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.formRow.col2.send{
justify-content: center;
}
.formRowChild.col2{
width:49%;
}
.formRow > label{
width:100%;
}
.formRow > label{
display:block;
margin-bottom:1.4rem;
}
.formRowChild.col2 > label{
width:100%;
display:block;
margin-bottom:1.4rem;
}
.formRow > .radioCheck{
display:inline-block;
width:auto;
background: #F2F2F2;
border-radius: 0.4rem;
padding: 0.4rem 2rem 0.4rem 1.6rem;
margin: 0 .8rem .8rem 0;
}
input[type="text" i],select,textarea{
width:100%;
font-size: 1.6rem;
color: #3f3f3f !important;
border: 1px solid #D9D9D9;
border-radius: .4rem;
padding: 0.6rem 1rem;
}
p.confirmText {
width: 100%;
font-size: 1.6rem;
color: #3f3f3f !important;
background:#ebebeb;
border: none;
border-radius: 0.4rem;
padding: 0.6rem 1rem;
overflow-wrap: break-word;
}
textarea {
resize: vertical;
}
button#submitButton{
font-size: 1.6rem;
width:26rem;
background: linear-gradient(90deg,#282828 0%,#282828 50%,#F93678 51%,#FE8B74 100%);
background-position: 1% 50%;
background-size: 204% auto;
border: none;
border-radius: 10rem;
padding: 0.9rem 0;
color: #fff;
display:block;
margin:0 auto;
transition: all .3s ease;
}
button#submitButton:hover{
background-position: 100% 51%;
cursor:pointer;
}
button#backButton{
font-size: 1.6rem;
width:26rem;
background: linear-gradient(90deg,#282828 0%,#282828 50%,#282828 51%,#5f5f5f 100%);
background-position: 1% 50%;
background-size: 204% auto;
border: none;
border-radius: 10rem;
padding: 0.9rem 0;
color: #fff;
display:block;
margin:0 1.6rem 0 0 ;
transition: all .3s ease;
}
button#backButton:hover{
background-position: 100% 51%;
cursor:pointer;
}
.formRow.col2.send button#submitButton{
margin:0 0 0 1.6rem ;
}
.submitError.form-invalid{
background: #FBECE9;
border: 1px solid #E07868;
border-radius: 4px;
padding: 1rem;
color: #E07868;
margin-bottom: 3.2rem;
}
.form-invalid{
background: #FBECE9;
border: 1px solid #E07868;
border-radius: 4px;
padding: 0.6rem 1rem;
color: #E07868;
margin-bottom: 3.2rem;
margin-top: 0.6rem;
}
@media(max-width:768px){
section.common{
width:96%;
}
.formRowChild.col2{
width:100%;
}
.formRow.col2 > .formRowChild.col2:nth-of-type(1){
margin-bottom:3.2rem;
}
button#backButton{
margin:0 auto 1.6rem ;
}
.formRow.col2.send button#submitButton{
margin:0 auto;
}
}
⑤リセット用スタイルシート(base.css)
/* Box sizing rules */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Remove default padding */
ul[class],
ol[class] {
padding: 0;
}
/* Remove default margin */
body,
h1,
h2,
h3,
h4,
p,
ul[class],
ol[class],
figure,
blockquote,
dl,
dd {
margin: 0;
}
/* Set core root defaults */
html {
scroll-behavior: smooth;
}
/* Set core body defaults */
body {
min-height: 100vh;
text-rendering: optimizeSpeed;
line-height: 1.5;
}
/* A elements that don't have a class get default styles */
a:not([class]) {
text-decoration-skip-ink: auto;
}
/* Make images easier to work with */
img {
max-width: 100%;
/*display: block;*/
}
/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
font: inherit;
}
各コードの解説
①入力画面(index.php)
まずは入力画面です。
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/style.css">
<script src="https://www.google.com/recaptcha/api.js?render=リキャプチャのキー"></script>
<head>タグ内でまずは必要な要素を読み込みましょう。
- Googleフォント【NotoSans】の呼び出し
- base.css(リセット用css)
- style.css(スタイルシート)
- Google reCAPTCHA のAPI呼び出し
をここでは行っています。
この際、Google reCAPTCHA サイトキーを「リキャプチャのキー」と書かれている部分に記載しておくことをお忘れなく。
なお、Google reCAPTCHA の詳しい使い方については下記を参考にしてみてくださいね。
<form action="confirm.php" method="POST" name="form">
前回と同じく、フォーム上のデータのやり取りはPOSTで行います。送信先は同ディレクトリのconfirm.phpとしましょう。
<input type='hidden' name='modeTo' value="confirm">
入力欄を設ける前に、type属性でhiddenを指定したinputをひとつ置いてやります。
次の項で詳しく解説しますが、このinputは入力画面→確認画面へ進んだことを判定するロジックとなります。
<div class="formRow col2">
<div class="formRowChild col2">
<label for="lastname"><span class="require">必須</span>性</label>
<input type="text" name="lastname" id="lastname" placeholder="例)山田" value="">
<p class="err-msg-last_name"></p>
</div>
<div class="formRowChild col2">
<label for="firstname"><span class="require">必須</span>名</label>
<input type="text" name="firstname" id="firstname" placeholder="例)太郎" value="">
<p class="err-msg-first_name"></p>
</div>
</div>
各フォームの入力欄については自由にやってください。
labelタグのfor属性と、対応する入力欄のname属性を一致させることをお忘れなく。
<p class="submitError"></p>
・
・
・
<p class="err-msg-last_name"></p>
またフォームの随所に記載されている上記のような<p>タグは、フォームのエラーメッセージを表示するのに必要になります。今回は各入力・選択項目に対して別々のエラーメッセージを表示させたい為、別々のclassを与えています。
<div class="formRow">
<label for="contact_method"><span class="any">任意</span>ご希望の連絡方法</label>
<label class="radioCheck"><input type="checkbox" name="contact_method[]" value="電話" checked>電話</label>
<label class="radioCheck"><input type="checkbox" name="contact_method[]" value="メール">メール</label>
<label class="radioCheck"><input type="checkbox" name="contact_method[]" value="どちらでもよい">どちらでもよい</label>
</div>
チェックボックスについては、2つ以上の選択が必要な場合もあると思います。
その際、最終的にvalueの値を配列に格納する必要があります。
ここで難しい話は避けるとして、とりあえずname属性の末尾に[]を入れておくのを忘れないようにしましょう。
<div class="formRow">
<button class="g-recaptcha" data-sitekey="リキャプチャのキー" data-action='submit' type="submit" id="submitButton">確認画面へ</button>
</div>
送信ボタンの方ではdata-sitekey属性を設けて、そこにリキャプチャのサイトキーを記載しておきましょう。他の属性値も必須なのでお忘れなく。
<script>
// バリデーション + リキャプチャ
window.addEventListener('DOMContentLoaded', () => {
const submits = document.querySelector('#submitButton');
submits.addEventListener('click', (e) => {
grecaptcha.ready(function () {
grecaptcha.execute('リキャプチャのキー', { action: 'submit' }).then(function (token) {
e.preventDefault();
// 姓名のチェック
const last_name = document.querySelector('#lastname');
const first_name = document.querySelector('#firstname');
const last_name_kana = document.querySelector('#lastname_kana');
const first_name_kana = document.querySelector('#firstname_kana');
// エラーメッセージを表示させる要素を取得
const errMsglast_name = document.querySelector('.err-msg-last_name');
const errMsgfirst_name = document.querySelector('.err-msg-first_name');
const errMsglast_name_kana = document.querySelector('.err-msg-last_name_kana');
const errMsgfirst_name_kana = document.querySelector('.err-msg-first_name_kana');
if (!last_name.value) {
errMsglast_name.classList.add('form-invalid');
errMsglast_name.textContent = '姓を入力してください';
} else {
errMsglast_name.textContent = '';
last_name.classList.remove('input-invalid');
errMsglast_name.classList.remove('form-invalid');
}
if (!first_name.value) {
errMsgfirst_name.classList.add('form-invalid');
errMsgfirst_name.textContent = '名を入力してください';
} else {
errMsgfirst_name.textContent = '';
first_name.classList.remove('input-invalid');
errMsgfirst_name.classList.remove('form-invalid');
}
if (!last_name_kana.value) {
errMsglast_name_kana.classList.add('form-invalid');
errMsglast_name_kana.textContent = '姓(カタカナ)を入力してください';
} else {
errMsglast_name_kana.textContent = '';
last_name_kana.classList.remove('input-invalid');
errMsglast_name_kana.classList.remove('form-invalid');
}
if (!first_name_kana.value) {
errMsgfirst_name_kana.classList.add('form-invalid');
errMsgfirst_name_kana.textContent = '名(カタカナ)を入力してください';
} else {
errMsgfirst_name_kana.textContent = '';
first_name_kana.classList.remove('input-invalid');
errMsgfirst_name_kana.classList.remove('form-invalid');
}
// メールアドレスのチェック
const mail = document.querySelector('#email');
const errMsgMail = document.querySelector('.err-msg-mail');
if (!mail.value.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/)) {
errMsgMail.classList.add('form-invalid');
errMsgMail.textContent = '正しいメールアドレスを入力してください';
mail.classList.add('input-invalid');
} else {
errMsgMail.textContent = '';
mail.classList.remove('input-invalid');
errMsgMail.classList.remove('form-invalid');
}
// 電話番号のチェック
const tel = document.querySelector('#tel');
const errMsgTel = document.querySelector('.err-msg-tel');
if (!tel.value.match(/^\(?\d{2,5}\)?[-(\.\s]{0,2}\d{1,4}[-)\.\s]{0,2}\d{3,4}$/)) {
errMsgTel.classList.add('form-invalid');
errMsgTel.textContent = '正しい電話番号を入力してください';
tel.classList.add('input-invalid');
} else {
errMsgTel.textContent = '';
tel.classList.remove('input-invalid');
errMsgTel.classList.remove('form-invalid');
}
// セレクトボックスのチェック
const inquiry = document.querySelector('#inquiry');
const errMsgInquiry = document.querySelector('.err-msg-inquiry');
if (!inquiry.value) {
errMsgInquiry.classList.add('form-invalid');
errMsgInquiry.textContent = '選択してください';
} else {
errMsgInquiry.textContent = '';
inquiry.classList.remove('input-invalid');
errMsgInquiry.classList.remove('form-invalid');
}
// テキストエリアのチェック
const textarea = document.querySelector('#textarea');
const errMsgTextarea= document.querySelector('.err-msg-textarea');
if (!textarea.value) {
errMsgTextarea.classList.add('form-invalid');
errMsgTextarea.textContent = '本文を入力してください';
} else {
errMsgTextarea.textContent = '';
textarea.classList.remove('input-invalid');
errMsgTextarea.classList.remove('form-invalid');
}
// フォーム上部にエラーメッセージを表示
const errMsgSubmit = document.querySelector('.submitError');
// フォームトップの高さを取得
const formPosition = document.querySelector('#form');
const errorElemOffsetTop = formPosition.offsetTop;
// フォーム上部にエラーメッセージを表示
if ((!tel.value.match(/^\(?\d{2,5}\)?[-(\.\s]{0,2}\d{1,4}[-)\.\s]{0,2}\d{3,4}$/)) || (!mail.value.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/)) || (!last_name.value) || (!first_name.value)|| (!last_name_kana.value) || (!first_name_kana.value) ||(!last_name_kana.value)||(!first_name_kana.value)||(!inquiry.value)||(!textarea.value)) {
errMsgSubmit.classList.add('form-invalid');
errMsgSubmit.textContent = '入力内容に誤りがあります。ご確認の上、再度入力してください。';
// フォームの先頭へスクロールさせる
window.scrollTo({
top: errorElemOffsetTop - 40,
behavior: 'smooth'
});
} else {
errMsgSubmit.textContent = '';
errMsgSubmit.classList.remove('form-invalid');
const form = document.getElementById('form');
form.submit();
}
});
});
}, false);
}, false);
</script>
最後のscriptではバリデーションを行っています。
まずはgrecaptcha.execute() でリキャプチャのサイトキーを書いておきましょう。
その後各入力項目のinputとエラーメッセージ表示用の<p>タグに割り振られたIDを参照させ、
入力(選択も)が空ではないか、不正な文字列が用いられていないかをチェックしています。
難しい場合はそのままコピペでも問題ないと思います。
最終的にエラーの場合はエラーメッセージを表示して、フォームの先頭へ強制スクロール。OKの場合は送信アクションを実行させます。
②確認画面 – 1回目(confirm.php)
続いては確認画面です。
index.phpからconfirm.phpにデータが送信される訳ですが、仕様上このロジックは2回使われることになります。
まずは1回目のロジックを見ていきましょう。
<?php
session_start();
// PHPMailer 必要なファイルを読み込み
require('./PHPMailer/PHPMailer/src/PHPMailer.php');
require('./PHPMailer/PHPMailer/src/Exception.php');
require('./PHPMailer/PHPMailer/src/SMTP.php');
セキュリティ上の問題で$SESSION変数を使用したい為、おまじないの「session_start();」を記述。
その後はPHP Mailerを呼び出しています。
composerを使う手がありますが、今回はダウンロードして使います。
公式サイトの「Code」→「Download Zip」をクリックすると、ファイル一式をダウンロードすることができます。

ファイルをダウンロードしたら、解凍します。
この際、「PHPMailer-master」というフォルダ名を「PHPMailer」にリネームしておきましょう。
if (isset($_POST['modeTo'])) {
if ($_POST['modeTo'] === 'confirm') {
$firstname = $_POST["firstname"];
$lastname = $_POST["lastname"];
$firstname_kana = $_POST["firstname_kana"];
$lastname_kana = $_POST["firstname_kana"];
$tel = $_POST["tel"];
$email = $_POST["email"];
$sex = $_POST["sex"];
$inquiry = $_POST["inquiry"];
if (isset($_POST['contact_method']) && is_array($_POST['contact_method'])) {
$contact_method = implode("、", $_POST["contact_method"]);
}
$textarea = $_POST["textarea"];
$_SESSION["firstname"] = $_POST["firstname"];
$_SESSION["lastname"] = $_POST["lastname"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["tel"] = $_POST["tel"];
$_SESSION["email"] = $_POST["email"];
$_SESSION["sex"] = $_POST["sex"];
$_SESSION["inquiry"] = $_POST["inquiry"];
$_SESSION["contact_method"] = implode("、", $_POST["contact_method"]);
$_SESSION["textarea"] = $_POST["textarea"];
}
}
index.phpからPOSTで送信したデータは、このconfirm.phpで一度受け取らせます。
まず最初の行のif (isset($_POST[‘modeTo’])) で、先の項で触れた <input type=’hidden’ name=’modeTo’>があるか判定させています。
また if ($_POST[‘modeTo’] === ‘confirm’)は入力画面で送信したinput name=’modeTo’ にvalue属性としてconfirmが指定されているかを判定させています。
この2つの条件がそろった場合、入力画面→確認画面へ進んだということになります。
この時POSTで受け取った入力欄のデータを、個別に変数に格納しておきます。
$”inputのname属性の名前” = $POST[“inputのname属性の名前”] とすると分かりやすいと思います。
セキュリティの問題もあるので$SESSION[“inputのname属性の名前”] = $POST[“inputのname属性の名前”]と、今度はSESSION変数に入れておくこともお忘れなく。
<form id="form" action="confirm.php" method="POST" name="form">
<input type='hidden' name='modeTo' value="send">
少し行を飛ばして、formタグの方へ。
確認画面ではユーザーが入力・選択した内容を確認させ、送信させます。
①で触れたのと同じく、データ送信にはPOSTを指定します。
actionにはこのconfirm.phpをもう一度指定してやります。
その下の<input type=’hidden’ name=’modeTo’ value=”send”> も①と同じ。
ただ今度は確認画面→送信完了のステップに切り替わったことを認識させたいので、valueをsendとしておきます。
<input id="firstname" type="hidden" name="firstname" value="<?php echo $firstname; ?>">
<input id="lastname" type="hidden" name="lastname" value="<?php echo $lastname; ?>">
<input id="firstname_kana" type="hidden" name="firstname_kana" value="<?php echo $firstname_kana; ?>">
<input id="lastname_kana" type="hidden" name="lastname_kana" value="<?php echo $lastname_kana; ?>">
<input id="email" type="hidden" name="email" value="<?php echo $email; ?>">
<input id="tel" type="hidden" name="tel" value="<?php echo $tel; ?>">
<input id="sex" type="hidden" name="sex" value="<?php echo $sex; ?>">
<input id="inquiry" type="hidden" name="inquiry" value="<?php echo $inquiry; ?>">
<input id="contact_method" type="hidden" name="contact_method" value="<?php echo $contact_method; ?>">
<input id="textarea" type="hidden" name="textarea" value="<?php echo $textarea; ?>">
また先ほどindex.phpからconfirm.phpに送った際、受け取った入力欄のデータを変数に格納したと思います。それをここで、type=”hidden”指定したinputに代入しておきます。
①から②に進んだ時点で、POSTで送信したデータは一度捨てて、メモ代わりのつもりで変数に格納、再度inputに代入するわけですね。
<div class="formRow col2 send">
<button type="button" value="内容を修正する" onclick="history.back()" id="backButton">内容を修正する</button>
<button class="g-recaptcha" data-sitekey="リキャプチャのキー" data-action='submit' type="submit" id="submitButton">送信する</button>
</div>
最後の行では送信ボタンの他に、内容を修正するボタンを設けています。内容に誤りがあった場合、ユーザーはこのボタンを押して前ページに戻ることが出来ます。
buttonタグに onclick=”history.back()” と記載することで、直前まで開いていたページ = index.phpにブラウザバックさせることが可能です。
POSTで送信したデータは失われていると書きましたが、前ページのブラウザキャッシュは残ったままなので、入力値・選択値は保持されているはずです。
</form>
</section>
<script>
// バリデーション + リキャプチャ
window.addEventListener('DOMContentLoaded', () => {
const submits = document.querySelector('#submitButton');
submits.addEventListener('click', (e) => {
grecaptcha.ready(function () {
grecaptcha.execute('リキャプチャのキー', { action: 'submit' }).then(function (token) {
e.preventDefault();
// 姓名のチェック
const last_name = document.querySelector('#lastname');
const first_name = document.querySelector('#firstname');
const last_name_kana = document.querySelector('#lastname_kana');
const first_name_kana = document.querySelector('#firstname_kana');
// メールアドレスのチェック
const mail = document.querySelector('#email');
// 電話番号のチェック
const tel = document.querySelector('#tel');
// セレクトボックスのチェック
const inquiry = document.querySelector('#inquiry');
// テキストエリアのチェック
const textarea = document.querySelector('#textarea');
// フォーム上部にエラーメッセージを表示
const errMsgSubmit = document.querySelector('.submitError');
// フォームトップの高さを取得
const formPosition = document.querySelector('#form');
const errorElemOffsetTop = formPosition.offsetTop;
// フォーム上部にエラーメッセージを表示
if ((!tel.value.match(/^\(?\d{2,5}\)?[-(\.\s]{0,2}\d{1,4}[-)\.\s]{0,2}\d{3,4}$/)) || (!mail.value.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/)) || (!last_name.value) || (!first_name.value)|| (!last_name_kana.value) || (!first_name_kana.value) ||(!last_name_kana.value)||(!first_name_kana.value)||(!inquiry.value)||(!textarea.value)) {
} else {
const form = document.getElementById('form');
form.submit();
}
});
});
}, false);
}, false);
</script>
バリデーションはindex.phpとほぼ共通です。
必要のない部分だけをそぎ落としているだけなので、説明は省きます。
②確認画面 – 2回目(confirm.php)
// 送信ボタンを押したら
if (isset($_POST['modeTo'])) {
if ($_POST['modeTo'] === 'send') {
$firstname = $_POST["firstname"];
$lastname = $_POST["lastname"];
$firstname_kana = $_POST["firstname_kana"];
$lastname_kana = $_POST["firstname_kana"];
$tel = $_POST["tel"];
$email = $_POST["email"];
$sex = $_POST["sex"];
$inquiry = $_POST["inquiry"];
$contact_method = $_POST["contact_method"];
$textarea = $_POST["textarea"];
$_SESSION["firstname"] = $_POST["firstname"];
$_SESSION["lastname"] = $_POST["lastname"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["firstname_kana"] = $_POST["firstname_kana"];
$_SESSION["tel"] = $_POST["tel"];
$_SESSION["email"] = $_POST["email"];
$_SESSION["sex"] = $_POST["sex"];
$_SESSION["inquiry"] = $_POST["inquiry"];
$_SESSION["contact_method"] = $_POST["contact_method"];
$_SESSION["textarea"] = $_POST["textarea"];
// 日本語エンコード
mb_language("uni");
mb_internal_encoding("UTF-8");
// インスタンス生成
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
// 文字エンコードを指定
$mail->CharSet = 'utf-8';
try {
// SMTPサーバの設定
$mail->isSMTP();
$mail->Host = 'SMTPサーバーを指定';
$mail->SMTPAuth = true;
$mail->Username = 'ユーザー名';
$mail->Password = 'パスワード'; // SMTPサーバーのパスワード
$mail->SMTPSecure = 'tls'; // 暗号化を有効(tls or ssl)無効の場合はfalse
$mail->Port = 587; // TCPポートを指定(tlsの場合は465や587)
// 送受信先設定(第二引数は省略可)
$mail->setFrom('送信元メールアドレス', '送信者名'); // 送信者
$mail->addAddress($email); // 宛先
$mail->addAddress('送信先メールアドレス'); // 宛先2
$mail->Sender = '送信できなかった場合の返送先'; // Return-path
// 送信内容設定
$mail->Subject = '[自動送信]お問い合わせ内容の確認';
$mail->Body =<<<EOM
{$lastname}{$firstname} 様
お問い合わせありがとうございます。
以下のお問い合わせ内容を、メールにて確認させていただきました。
===================================================
【 お名前 】
{$lastname}{$firstname}
【 フリガナ 】
{$lastname_kana}{$firstname_kana}
【 メール 】
{$email}
【 電話番号 】
{$tel}
【 性別 】
{$sex}
【 お問い合わせ内容 】
{$inquiry}
【 ご希望の連絡方法 】
{$contact_method}
【 メッセージ本文 】
{$textarea}
===================================================
内容を確認のうえ、回答させて頂きます。
しばらくお待ちください。
EOM;
// 送信
$mail->send();
header("Location: リダイレクト先のURLを記載");
} catch (Exception $e) {
// エラーの場合
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}}
$_SESSION = [];
session_destroy();
?>
少し戻ります。
確認画面から送信ボタンを押すと、データは再度このconfirm.phpに送信されます。
そして<input type=’hidden’ name=’modeTo’> で value=”send” と指定していたので、今度はこちらのロジックが発動するわけですね。
最初にPOSTした値を変数に格納するのは同じですが、それ以降は暗記する呪文=コピペOKだという風に考えてもらっても大丈夫です。いきなり初心者の方がこれを理解するのは難しいかもしれません。
一応、呪文が何をしているのか解説しておきます。
// 日本語エンコード
mb_language("uni");
mb_internal_encoding("UTF-8");
// インスタンス生成
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
// 文字エンコードを指定
$mail->CharSet = 'utf-8';
ここではまず日本語エンコードを行っています。
この処理を行わないと、実際のメールの文章が文字化けしたりする事故が発生します。
その次はPHP Mailerのインスタンス生成、日本語エンコードです。
try {
// SMTPサーバの設定
$mail->isSMTP();
$mail->Host = 'SMTPサーバーを指定';
$mail->SMTPAuth = true;
$mail->Username = 'ユーザー名';
$mail->Password = 'パスワード';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
// 送受信先設定
$mail->setFrom('送信元メールアドレス', '送信者名'); // 送信者
$mail->addAddress($email); // 宛先
$mail->addAddress('送信先メールアドレス'); // 宛先2
$mail->Sender = '送信できなかった場合の返送先'; // Return-path
// 送信内容設定
$mail->Subject = '[自動送信]お問い合わせ内容の確認';
$mail->Body =<<<EOM
{$lastname}{$firstname} 様
・
・
・
EOM;
try以降、最初に行っているのはSMTPの設定・送受信内容の設定です。
そのままコピペ & 必要な情報入力でそのまま動くと思います。
今回はエックスサーバーなどのレンタルサーバー利用を想定していますが、Gmailとかでも可能です。
その後メールタイトル・本文を設定しています。
// 送信
$mail->send();
header("Location: リダイレクト先のURLを記載");
} catch (Exception $e) {
// エラーの場合
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}}
$_SESSION = [];
session_destroy();
すべての情報を設定した後、フォームからメールを飛ばします。
メールが送信できた後は、リダイレクトさせる場合はそのURLをheader関数に記載しましょう。
再度にstartさせたsessionが残っているので、最後の2行で無効化して終わりです。
③完了画面(complete.php)
先ほどheader(); で指定したURLにはこのファイルを置いておきましょう。
③スタイルシート関連
さすがにCSSの解説は不要だと思います。
ちなみに上記のコードをコピペして表示させると下記のようになります。
好みで色合いなどは調整してみてください。

Webデザイナーを目指すあなたへ
以下の記事では、Webデザインスクールの厳選3校をご紹介しています。
是非参考にしてみてくださいね。