お問い合わせフォームは、多くのウェブサイトで必要とされる重要な機能です。本記事では、Vue.jsを使って動的なユーザーインターフェイスを作り、PHPを使って問い合わせ内容を処理・送信するシンプルなフォームを構築します。
使用したツールとバージョン情報
- Vue.js: 3.x (CDN経由で最新バージョンを使用 ※テストは 3.5.13)
- Tailwind CSS: 3.x (CDN経由で最新バージョンを使用 ※テストは 3.4.15)
- PHP: 8.2.22
- エックスサーバー
完成イメージ
このお問い合わせフォームは以下の3ステップで動作します:
- 入力画面:ユーザーが名前、メールアドレス、お問い合わせ内容を入力。
- 確認画面:入力内容を確認し、修正または送信が可能。
- 完了画面:送信完了メッセージを表示。
さらに、以下の機能を実装しています:
- 動的な画面遷移: Vue.jsでステップごとに画面を切り替え。
- 自動返信メール: 問い合わせ者に確認メールを送信。
- レスポンシブデザイン: Tailwind CSS
必要な技術
- Vue.js: データバインディングとリアクティブな画面更新。
- PHP: メール送信や問い合わせ内容の処理。
- Tailwind CSS: デザインの適用。
コードの全体像
1. フロントエンド (index.html)
以下のHTMLコードでは、Vue.jsを利用して画面を動的に切り替え、Tailwind CSSでデザインを整えています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>お問い合わせフォーム</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center">
<div id="app" class="bg-white shadow-md rounded p-6 w-full max-w-md">
<!-- 入力ページ -->
<div v-if="currentStep === 'input'">
<h1 class="text-2xl font-bold mb-4">お問い合わせフォーム</h1>
<form @submit.prevent="goToConfirm">
<div class="mb-4">
<label for="name" class="block text-sm font-medium text-gray-700">名前:</label>
<input type="text" v-model="formData.name" id="name" required
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div class="mb-4">
<label for="email" class="block text-sm font-medium text-gray-700">メールアドレス:</label>
<input type="email" v-model="formData.email" id="email" required
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div class="mb-4">
<label for="message" class="block text-sm font-medium text-gray-700">お問い合わせ内容:</label>
<textarea v-model="formData.message" id="message" required
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"></textarea>
</div>
<button type="submit" class="w-full bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700">
確認画面へ
</button>
</form>
</div>
<!-- 確認ページ -->
<div v-if="currentStep === 'confirm'">
<h1 class="text-2xl font-bold mb-4">内容の確認</h1>
<p class="mb-2"><strong>名前:</strong> {{ formData.name }}</p>
<p class="mb-2"><strong>メールアドレス:</strong> {{ formData.email }}</p>
<p class="mb-4"><strong>お問い合わせ内容:</strong> {{ formData.message }}</p>
<div class="flex space-x-4">
<button @click="currentStep = 'input'" class="w-1/2 bg-gray-600 text-white py-2 px-4 rounded hover:bg-gray-700">
戻る
</button>
<button @click="submitForm" class="w-1/2 bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700">
送信する
</button>
</div>
</div>
<!-- 完了ページ -->
<div v-if="currentStep === 'complete'">
<h1 class="text-2xl font-bold mb-4">送信が完了しました</h1>
<p>お問い合わせいただきありがとうございます。</p>
<button @click="resetForm" class="mt-4 w-full bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700">
フォームに戻る
</button>
</div>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
currentStep: 'input', // 現在のステップ ('input', 'confirm', 'complete')
formData: {
name: '',
email: '',
message: ''
}
};
},
methods: {
resetForm() {
this.formData = {
name: '',
email: '',
message: ''
};
this.currentStep = 'input';
},
goToConfirm() {
this.currentStep = 'confirm';
},
async submitForm() {
try {
const response = await fetch('backend/contact.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(this.formData)
});
const data = await response.json();
if (data.success) {
this.currentStep = 'complete';
} else {
alert('送信に失敗しました: ' + (data.error || '不明なエラー'));
this.currentStep = 'input';
}
} catch (error) {
alert('エラーが発生しました。');
this.currentStep = 'input';
}
}
}
}).mount('#app');
</script>
</body>
</html>
2. バックエンド (contact.php)
以下のPHPコードは、問い合わせ内容を処理し、管理者への通知と自動返信メールを送信します。
<?php
header('Content-Type: application/json');
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['name']) || empty($data['email']) || empty($data['message'])) {
echo json_encode(['success' => false, 'error' => '入力内容が不完全です。']);
exit;
}
// 管理者への通知メール
$toAdmin = 'admin@example.com'; // 仮の送信先アドレス
$subjectAdmin = 'お問い合わせフォームからのメッセージ';
$messageAdmin = "名前: {$data['name']}\nメールアドレス: {$data['email']}\nメッセージ: {$data['message']}";
$headersAdmin = 'From: noreply@example.com'; // 仮のFromアドレス
$mailToAdmin = mail($toAdmin, $subjectAdmin, $messageAdmin, $headersAdmin);
// 問い合わせ者への自動返信メール
$toUser = $data['email'];
$subjectUser = 'お問い合わせありがとうございます';
$messageUser = "{$data['name']} 様\n\nお問い合わせありがとうございます。\n以下の内容で受け付けました。\n----------------------\nお名前: {$data['name']}\nメールアドレス: {$data['email']}\nお問い合わせ内容:\n{$data['message']}\n----------------------\n\n担当者より折り返しご連絡いたします。";
$headersUser = 'From: noreply@example.com'; // 仮のFromアドレス
$mailToUser = mail($toUser, $subjectUser, $messageUser, $headersUser);
if ($mailToAdmin && $mailToUser) {
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'error' => 'メール送信に失敗しました。']);
}
Vue.jsの動きの説明
ステップ遷移
currentStep
というデータを利用して、画面の状態を管理します。v-if
ディレクティブで以下を切り替えます:
input
: 入力画面confirm
: 確認画面complete
: 完了画面
データバインディング
formData
オブジェクトをv-model
で各入力フィールドとバインド。これにより、フォームの
入力値がリアルタイムで更新されます。
非同期通信
submitForm
メソッドでfetch
を使用してPHPスクリプトにデータを送信し、サーバーのレスポンスを処理します。
コメント