フォーム生成ライブラリ作ってみた

要素の多いフォームを作るのが面倒だったのでフォーム生成ライブラリ作ってみた
実際はSmarty使うだろうからおそらくもっと楽
 
つかいかた
・addXXX() で要素追加
・checkXXX() で入力チェック項目追加
・setValue() で初期値セット
・getForm() でフォーム要素のHTMLを配列を取得
・getConfirm() で確認画面用の表示用HTMLを配列を取得
・getInput() で送信用のhiddenのinputを取得
・getArray() でエスケープしていない値を配列で取得
・getError() で入力エラーメッセージを配列で取得
・hasError() エラーがあるか否か
 
機能
・$reqを引数に渡して初期値指定
・入力チェック
・1つの要素に対して最初に出たエラー以外出さない
クロスサイトリクエストフォージェリ対策
 
入力チェック方法
・最小文字数/最小選択数
・最大文字数/最大選択数
・英数字か否か (Ctype)
・英字か否か (Ctype)
・制御文字か否か (Ctype)
・数字か否か (Ctype)
・空白以外の印字可能な文字か否か (Ctype)
・小文字か否か (Ctype)
・印字可能な文字か否か (Ctype)
・空白、英数字以外の出力可能な文字か否か (Ctype)
・空白文字か否か (Ctype)
・大文字か否か (Ctype)
・16進数を表す文字か否か (Ctype)
・空入力/未選択
・マッチ (preg)
 
デメリット
・デザインを適用しづらい
 

<?php
require_once(dirname(__FILE__).'/Form.php');
$req = array_merge($_GET,$_POST);
session_start();

$form = new Form();
// データセット
$form->addText('name');
$form->addText('age');
$form->addRadio('gender',array('male'=>'','female'=>''));
$form->addCheckbox('hobby',explode(',','映画鑑賞,スポーツ,スポーツ観戦,音楽鑑賞,カラオケ・バンド,料理,グルメ,お酒,ショッピング,ファッション,アウトドア,ドライブ,旅行,アート,習いごと,語学読書,マンガ,テレビ,ゲーム,インターネット,ギャンブル,ペット,美容・ダイエット'));
$form->addSelect('job',explode(',','IT関係,事務系,技術系,営業・企画系,クリエーター系,販売系,サービス業,ガテン系,役員・管理職,専門職,公務員,教員,自営業,アーティスト,フリーター,大学生・院生,専門学校生,主婦,求職中,その他'),'▼選択');
$form->addText('email');
$form->addTextarea('profile');
$form->addPassword('pass');
$form->addSubmit('確認');

// 入力チェック
$form->checkEmpty('name','名前を入力してください');
$form->checkMax('name',20,'名前は20文字以内で入力してください');
$form->checkEmpty('age','年齢を入力してください');
$form->checkCtype('age','digit','年齢は半角数字のみで入力してください');
$form->checkEmpty('gender','性別を選択してください');
$form->checkMin('hobby',2,'趣味は最低2個以上選択してください');
$form->checkEmpty('job','職業を選択してください');
$form->checkEmpty('email','メールアドレスを入力してください');
$form->checkMatch('email','/^[a-zA-Z0-9\-_\.]+@[a-zA-Z0-9\-_\.]+$/','メールアドレスを正しく入力してください');
$form->checkEmpty('profile','自己紹介を入力してください');
$form->checkMax('profile',100,'自己紹介は100文字以内で入力してください');
$form->checkEmpty('pass','パスワードを入力してください');
$form->checkCtype('pass','alnum','パスワードは半角英数字で入力してください');
$form->checkMin('pass',4,'パスワードを4文字以上入力してください');


// チェック
$mode = 'form';
// 完了画面
if(isset($req['mode']) && $req['mode']=='finish'){
	// 初期値セット
	$form->setValue($req);
	// 入力チェック
	$form->checkToken('post_token','Tokenが一致しません');
	$form->doCheck();
	$form->delToken('post_token');
	// 表示ページ
	$mode = 'finish';
	if($form->hasError()){
		$mode = 'error';
	}

// 確認画面
}elseif(isset($req['mode']) && $req['mode']=='confirm'){
	// 初期値セット
	$form->setValue($req);
	$form->addHidden('mode','finish');
	// 入力チェック
	$form->doCheck();
	// トークンセット
	$form->addToken('post_token');
	// 表示ページ
	$mode = 'confirm';
	if($form->hasError()){
		$mode = 'error';
	}

// 初期画面
}else{
	// 初期値セット
	$form->setValue($req);
	$form->addHidden('mode','confirm');
}


// 出力
$body = "<h1>{$mode}</h1>\n\n";
// 完了画面
if($mode=='finish'){
	foreach($form->getConfirm() as $name=>$input){
		$body .= sprintf("<b>%s:</b><br />\n%s<br />\n\n",$name,$input);
	}
	$body .= '<a href="">さいしょから</a><br />'."\n";
	$body .= print_r($form->getArray(),1);

// 確認画面
}elseif($mode=='confirm'){
	$form->addHidden('mode','finish');
	// 確認表示
	foreach($form->getConfirm() as $name=>$input){
		$body .= sprintf("<b>%s:</b><br />\n%s<br /><br />\n\n",$name,$input);
	}
	// 送信
	$body .= '<form action="" method="post">'."\n";
	$form->addHidden('mode','finish');
	$form->addSubmit('送信');
	$body .= $form->getInput();
	$body .= '</form>'."\n\n";
	// 戻る
	$body .= '<form action="" method="post">'."\n";
	$form->addHidden('mode','edit');
	$form->addSubmit('戻る');
	$body .= $form->getInput();
	$body .= '</form>'."\n\n";

// 初期画面
}else{
	$form->addHidden('mode','confirm');
	foreach($form->getError() as $err){
		$body .= sprintf("# %s<br />\n",$err);
	}
	$body .= '<form action="" method="post">'."\n\n";
	foreach($form->getForm() as $name=>$input){
		$body .= sprintf("<b>%s:</b><br />\n%s<br /><br />\n\n",$name,$input);
	}
	$body .= "</form>\n";
}


?>
<?='<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<!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" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="content-style-type" content="text/css" />
<style type="text/css">
body{
	font-size: 12px;
}
</style>
<title>フォーム生成</title>
</head>

<body>
<?=$body;?>
</body>
</html>

 
久々の休みだ!
OpenSocial系の仕事、一応終わった!一応リリース!大変だった!