ウェブ、ショウジン

PHPによるアンケートフォームの作成例

2009-1-10
Category
PHP

作成のための下準備

Smartyのカスタム設定

入力データのvalidationチェック

エラーチェック処理の準備
フォーム入力項目のエラーチェック処理

複数ファイルで利用する関数をまとめておく

MySmartyクラスの読み込み
セッション開始
エラーチェックなど

/opt/local/apache2/libs/function.php

<?php
// どのページでも利用するものをinit()関数として作成
function init() {
	// MySmartyクラスの読み込み
	require_once($_SERVER["DOCUMENT_ROOT"]."/../libs/MySmarty.class.php");

	// セッション開始
	session_start();
	// 定期的にセッションIDを変更する指定
	session_regenerate_id(true);
}

// 性別の配列を返す関数
function getSexList() {
	$sex_value = array(
		"1" => "男性",
		"2" => "女性"
	);
	return $sex_value;
}

// 年代の配列を返す関数
function getAgeList() {
	$age_value = array(
		"1" => "10代",
		"2" => "20代",
		"3" => "30代",
		"4" => "40代",
		"5" => "50代",
		"6" => "60代"
	);
	return $age_value;
}

// 動物の配列を返す関数
function getAnimalList() {
	$animal_value = array(
		"1" => "イヌ",
		"2" => "ネコ",
		"3" => "ライオン",
		"4" => "キリン",
		"5" => "虎",
		"6" => "ウサギ",
		"7" => "猿",
		"8" => "ペンギン",
		"9" => "馬",
		"10" => "象"
	);
	return $animal_value;
}

// エラーチェックのための関数
function error_check($check_data) {

	// エラーメッセージを格納する配列変数を初期化
	$error_list = array();

	// 名前の入力チェック開始
	// isset関数で名前の変数が存在するか確認し、trim関数で空白文字を削除した状態で
	// 名前が空の場合のエラーメッセージをセット
	if (isset($check_data["name"]) &amp;&amp; trim($check_data["name"]) === "") {
		$error_list[] = "名前を入力してください。";
	} elseif (mb_strlen($check_data["name"]) > 100) {
		$error_list[] = "名前は100文字以内で入力してください。";
	}

	// 性別のエラーチェック開始
	// 性別の変数が存在しない場合はエラー
	if (!isset($check_data["sex"])) {
		// エラーメッセージをセット
		$error_list[] = "性別を選択してください。";
		// 性別の配列を取得
		// 取得した値が性別の配列のキーに存在しない場合のエラーメッセージをセット
	} elseif (!array_key_exists($check_data["sex"], getSexList())) {
		$error_list[] = "正しい性別を選択してください。";
	}

	// 年代のエラーチェック開始
	// 年代の変数が入力されている場合のみエラーチェックを行う
	if (isset($check_data["age"]) &amp;&amp; $check_data["age"] !== "") {
		// 年代の配列を取得し、取得した値が年代の配列のキーに存在しない場合のエラーメッセージをセット
		if (!array_key_exists($check_data["age"], getAgeList())) {
			$error_list[] = "正しい年代を選択してください。";
		}
	}

	// 好きな動物のエラーチェック開始
	// ひとつも選択しなかった場合のエラーメッセージをセット
	if (!isset($check_data["animal"]) || !is_array($check_data["animal"])) {
		$error_list[] = "お好きな動物を最低ひとつは選択してください。";
	} else {
		// foreachで展開
		foreach ($check_data["animal"] as $check_value) {
			// 好きな動物の配列を取得
			// 取得した値が動物の配列のキーに存在しない場合のエラーメッセージをセット
			if (!array_key_exists($check_value, getAnimalList())) {
				$error_list[] = "正しい動物を選択してください。";
				break;
			}
		}
	}

	// コメントのエラーチェック開始
	// コメントが空の場合のエラーメッセージをセット
	if (isset($check_data["comment"]) &amp;&amp; $check_data["comment"] === "") {
		$error_list[] = "コメントを入力してください。";
	// 空白文字を削除した上でコメントが空の場合のエラーメッセージをセット
	} elseif (trim($check_data["comment"]) === "") {
		$error_list[] = "コメントを入力してください。";
	// コメントの文字列が1000文字を超えていた時のエラーメッセージをセット
	} elseif (mb_strlen($check_data["comment"]) > 1000) {
		$error_list[] = "コメントは1000文字以内で入力してください。";
	}


	// 配列形式でエラーメッセージが格納されている変数を戻り値として返す
	// エラーがない場合はarray()が返る
	return $error_list;
}

// データベースへの接続処理を関数として作成して利用する

// db_connectという名前の関数を作成
function db_connect() {

	// PEAR::DBライブラリの読み込み
	require_once("DB.php");

	// データベースへの接続情報を記述
	$dsn = "mysql://dbuser:hoge@localhost/phplesson";



	// データベースに接続
	$db = DB::connect($dsn);

	// 接続情報にエラーがないか確認
	if (PEAR::isError($db)) {
		print "データベースへの接続に失敗しました。";
		die($db->getMessage());
	}

	// 接続されたオブジェクトを返す
	return $db;
}

?>

入力フォームのロジックファイル(PHP)の作成

/opt/local/apache2/htdocs/php_10days/input.php

<?php
// libsに作成した共通関数を読み込む
require_once($_SERVER["DOCUMENT_ROOT"]."/../libs/function.php");

// 初期化関数の呼び出し(session開始とMySmartyクラスの読み込みをする)
init();


// エラーメッセージを受け取る変数の初期化
$error_list = array();

// フォームで入力した各アンケートデータをセッションに格納
if (isset($_POST["confirm"])) {

	$_SESSION["name"] = isset($_POST["name"]) ? $_POST["name"] : "";
	$_SESSION["sex"] = isset($_POST["sex"]) ? $_POST["sex"] : "";
	$_SESSION["age"] = isset($_POST["age"]) ? $_POST["age"] : "";
	$_SESSION["animal"] = isset($_POST["animal"]) ? $_POST["animal"] : "";
	$_SESSION["comment"] = isset($_POST["comment"]) ? $_POST["comment"] : "";

	// エラーチェック関数を呼び出し、エラーメッセージリストを受け取る
	$error_list = error_check($_SESSION);

	// エラーがなければ確認画面へ遷移
	if (!$error_list) {
		// 変数$urlにリダイレクト先である確認画面へのパス&ファイル名を代入
		// dirnameと$_SERVER["SCRIPT_NAME"]を併用することで
		// 実行ファイルのディレクトリ名を取得することが出来る
		$url = "http://".$_SERVER["HTTP_HOST"].dirname($_SERVER["SCRIPT_NAME"])."/confirm.php";
		// header関数で確認画面へリダイレクトさせる
		header("Location: ".$url);
		exit;
	}
}

// MySmartyクラスを生成
$smarty = new MySmarty();

// 性別、年齢、動物の各リストの配列をassignする
$smarty->assign("sex_value", getSexList());
$smarty->assign("age_value", getAgeList());
$smarty->assign("animal_value", getAnimalList());

// エラーメッセージリストをassign
$smarty->assign("error_list", $error_list);

// 表示するテンプレートを指定
$smarty->display("input.tpl");
?>

入力フォーム用テンプレートの作成

一度入力された値はデフォルト値として入力状態を保ったままにしておく。(エラーがあった場合に、いちいち入力し直すのはユーザに迷惑なので)

入力フォームにおける各項目のデフォルト設定について

/opt/local/apache2/templates/input.tpl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>アンケートフォーム</title>
</head>
<body>

<h1>アンケートフォーム</h1>

<!-- エラーメッセージがある場合の表示処理 start -->
{{if $error_list}}
	<div class="err">
		<!-- エラーメッセージの配列を展開して表示 -->
		{{foreach from=$error_list item=message}}
			<p>{{$message}}</p>
		{{/foreach}}
	</div>
{{/if}}
<!-- エラーメッセージがある場合の表示処理 end -->

<form action="input.php" method="POST">

<table class="enqform">
	<tr>
		<th>名前</th>
		<td>
			<input type="text" name="name" value="{{$smarty.session.name}}">
		</td>
	</tr>
	<tr>
		<th>性別</th>
		<td>
			{{html_radios name="sex" options=$sex_value selected=$smarty.session.sex label_ids=true separator="<br />"}}
		</td>
	</tr>
	<tr>
		<th>年代</th>
		<td>
			<select name="age">
				<option value="">選択してください</option>
				{{html_options selected=$smarty.session.age options=$age_value}}
			</select>
		</td>
	</tr>
	<tr>
		<th>好きな動物</th>
		<td>
			{{html_checkboxes name="animal" selected=$smarty.session.animal separator="<br />" options=$animal_value}}
		</td>
	</tr>
	<tr>
		<th>コメント</th>
		<td>
			<textarea rows="10" cols="40" name="comment">
				{{$smarty.session.comment}}
			</textarea>
		</td>
	</tr>
	<tr>
		<td colspan="2">
			<input type="submit" name="confirm" value="登録確認" />
		</td>
	</tr>
</table>
</body>
</html>

確認画面の作成

この確認画面へ、正しい遷移でもって来たかどかを確かめる必要がある。(URLを直打ちでアクセスしてくる可能性があり、それでは意味がないし問題あり)

入力フォーム画面で各項目が正しく入力された上で確認画面へ遷移してきたかを確認するには、function.phpに記述したerror_check関数が利用出来る。

入力フォーム画面で入力された各値はセッションに格納されているので、このセッションを確かめる。正しく入力されていない場合は再度、入力フォーム画面へ強制的にリダイレクトさせるように作る。

入力画面でユーザに入力してもらった各値を「人間が見て分かりやすい」文字列にして表示する必要がある。(例えば、配列キー名のままなら性別は「男」が1,「女」が2であるので、これを「男・女」に変換する必要がある)

確認画面には「登録」と「修正」の二つのボタンがある。それぞれがクリックされたときの処理を記述。

確認画面のロジックファイル

/opt/local/apache2/htdocs/php_10days/confirm.php

<?php
// 共通関数の読み込み
require_once($_SERVER["DOCUMENT_ROOT"]."/../libs/function.php");

// 初期化関数の呼び出し
init();

// error_check関数を使って正しい入力をした上で遷移してきたか確認する
if (error_check($_SESSION)) {
	// イレギュラーな遷移を経てこのページに辿り着いた場合の
	// リダイレクト先変数$urlに格納
	$url = "http://".$_SERVER["HTTP_HOST"].dirname($_SERVER["SCRIPT_NAME"])."/input.php";
	// header関数を使ってリダイレクト先へとばす
	header ("Location: ".$url);
	exit;
}

// modifyかregisterかで処理を分岐
if (isset($_POST["modify"])) {
	// 修正ボタンが押されたときの処理(入力フォームへとばす)
	$url = "http://".$_SERVER["HTTP_HOST"].dirname($_SERVER["SCRIPT_NAME"])."/input.php";
	header("Location: ".$url);
	exit;
}

// 登録ボタンが押されたときの処理
if (isset($_POST["register"])) {

	// データベースに接続する処理をまとめた関数を呼び出す
	$db = db_connect();

	// PEAR::DBのquoteSmartメソッドを使用してSQLで使用してはいけない文字列をエスケープ
	$name_val = $db->quoteSmart($_SESSION["name"]);
	$sex_val = $db->quoteSmart($_SESSION["sex"]);
	$age_val = $db->quoteSmart($_SESSION["age"]);
	$animal_val = $db->quoteSmart(join(",",$_SESSION["animal"]));
	$comment_val = $db->quoteSmart($_SESSION["comment"]);

	// 不要なセッションを削除
	// データ登録後は必ずデータを格納していたセッションをクリアする
	// さもないと同じデータを何度も繰り返し登録可能なスクリプトになる
	$_SESSION = array();

	$sql = "INSERT INTO anq_t(name,sex,age,animal,comment,del_flag,create_datetime) VALUES ({$name_val},{$sex_val},{$age_val},{$animal_val},{$comment_val},'0',now())";
	$res = $db->query($sql);

	// 登録処理が正常にいかなかった場合はエラーメッセージを出力してスクリプト終了
	if (DB::isError($res)) {
		print "エラーが発生しました。再度アンケートフォームよりご登録ください。<br />";
		exit;
	}

	// 完了画面を表示して終了
	$smarty = new MySmarty();
	$smarty->display("complete.tpl");
	exit;
}

// Smartyクラスを生成
$smarty = new MySmarty();

// 性別、年齢、好きな動物の各配列
$smarty->assign ("sex_value", getSexList());
$smarty->assign ("age_value", getAgeList());
$smarty->assign ("animal_value", getAnimalList());

// 表示するテンプレートを指定
$smarty->display ("confirm.tpl");

?>

確認画面のためのテンプレートファイル

/opt/local/apache2/templates/confirm.tpl

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="../css/enq.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>アンケート確認画面</title>
</head>
<body>
	<h1>アンケート入力内容の確認</h1>

	<div class="enq">
		<dl>
			<dt>名前</dt>
			<dd>
				{{* セッションに格納されている名前を表示 *}}
				{{$smarty.session.name}}
			</dd>
		</dl>
		<dl>
			<dt>性別</dt>
			<dd>
				{{* セッションに格納されている性別のキーを取り出して値に変換して表示 *}}
				{{$sex_value[$smarty.session.sex]}}
			</dd>
		</dl>
		<dl>
			<dt>年代</dt>
			<dd>
				{{* 性別と同じように配列のキーを取り出して値に変換して表示 *}}
				{{$age_value[$smarty.session.age]}}
			</dd>
		</dl>
		<dl>
			<dt>好きな動物</dt>
			<dd>
				{{* 好きな動物が格納されている配列を展開 *}}
				{{foreach from=$smarty.session.animal item=animal name=animal}}
					{{if $smarty.foreach.animal.first}}
						{{$animal_value[$animal]}}
					{{else}}
						, {{$animal_value[$animal]}}
					{{/if}}
				{{/foreach}}
			</dd>
		</dl>
		<dl>
			<dt>コメント</dt>
			<dd>
				{{* セッションに格納されているコメントの内容を改行コードを<br />に変換する修飾子を実行して表示 *}}
				{{$smarty.session.comment|nl2br}}
			</dd>
		</dl>

		<ul>
			<form action="confirm.php" method="post">
			<li><input type="submit" name="register" value="登録" /></li>
			<li><input type="submit" name="modify" value="修正" /></li>
			</form>
		</ul>

	</div>

</body>
</html>

アンケート登録完了画面のためのテンプレートファイル

/opt/local/apache2/templates/complete.tpl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html"; charset=UTF-8" />
<title>アンケート登録完了</title>
</head>
<body>
<h1>アンケート登録完了</h1>
<p>アンケートにご協力ありがとうございました。</p>
</body>
</html>

Categories

Tag Cloud

AdMob Android Apache centos CodeIgniter EC-CUBE facebookアプリ facebookページ feed Firefox Flash google googleanalytics htaccess iPad iPhone JavaScript lamp mobile nginx ogp pear php plugin rollover rss sendmail setting smarty ssh Titanium Mobile Titanium Studio tutorial ubuntu vim VirtualBox vmware vps Windows WordPress xampp youtube さくらインターネット アクセス解析 カスタム投稿