Smarty + HTML_QuickForm でフォーム作成2

概要

Smarty と HTML_QuickForm の今までの応用で少し大きめのフォームを作成してみます。
必要なファイルは以下の4つです。

目次

FourthStepQuickForm.php(クラスファイル)

addGroupRule で numeric 指定すると必須入力になるようです。
必須入力を回避させるために regex で正規表現のルールを作成しました。

今回は javascript での検証は行わず、サーバーサイドでのみ入力値チェックを行っています。

<?php  // /var/www/html/FourthStepQuickForm.php

  require_once "HTML/QuickForm.php";
  require_once "HTML/QuickForm/Renderer/ArraySmarty.php"; 

class FourthStepQuickForm {
  var $_form;

  // コンストラクタ($argAction :「送信」ボタンのリンク先) HTML_QuickForm オブジェクトを生成
  function FourthStepQuickForm($argAction) {
    $this->_form = new HTML_QuickForm('fourthForm', 'post', $argAction);
    $this->_form->_requiredNote = '<span style="color:#ff0000;">*</span> 必須入力';
  }

  // フォームに要素を追加
  function setItem() {
    // お名前
    $this->_form->addElement('text', 'name', 'お名前', array('id' => 'name', 'size' => 50, 'maxlength' => 30));
    $this->_form->addElement('text', 'namekana', 'お名前(かな)', array('id' => 'namekana', 'size' => 50, 'maxlength' => 30));
    // email
    $this->_form->addElement('text', 'email', 'e-mail', array('id' => 'email', 'size' => 50, 'maxlength' => 30));
    $this->_form->addElement('text', 'email2', 'e-mail確認', array('id' => 'email2', 'size' => 50, 'maxlength' => 30));
    // 郵便番号のグループ 
    $zipArray[] = &HTML_QuickForm::createElement('text', 0, null, array('id' => 'zip0', 'size' => 6, 'maxlength' => 3));
    $zipArray[] = &HTML_QuickForm::createElement('text', 1, null, array('id' => 'zip1', 'size' => 8, 'maxlength' => 4));
    $this->_form->addGroup($zipArray, 'zip', '郵便番号', ' - ');
    // 都道府県
    $areaArray = array(
      "北海道"=>"北海道",  "青森県"=>"青森県",  "岩手県"=>"岩手県",  "宮城県"=>"宮城県",
      "秋田県"=>"秋田県",  "山形県"=>"山形県",  "福島県"=>"福島県",  "茨城県"=>"茨城県",
      "栃木県"=>"栃木県",  "群馬県"=>"群馬県",  "埼玉県"=>"埼玉県",  "千葉県"=>"千葉県",
      "東京都"=>"東京都",  "神奈川県"=>"神奈川県",  "新潟県"=>"新潟県",  "富山県"=>"富山県",
      "石川県"=>"石川県",  "福井県"=>"福井県",  "山梨県"=>"山梨県",  "長野県"=>"長野県",
      "岐阜県"=>"岐阜県",  "静岡県"=>"静岡県",  "愛知県"=>"愛知県",  "三重県"=>"三重県",
      "滋賀県"=>"滋賀県",  "京都府"=>"京都府",  "大阪府"=>"大阪府",  "兵庫県"=>"兵庫県",
      "奈良県"=>"奈良県",  "和歌山県"=>"和歌山県",  "鳥取県"=>"鳥取県",  "島根県"=>"島根県",
      "岡山県"=>"岡山県",  "広島県"=>"広島県",  "山口県"=>"山口県",  "徳島県"=>"徳島県",
      "香川県"=>"香川県",  "愛媛県"=>"愛媛県",  "高知県"=>"高知県",  "福岡県"=>"福岡県",
      "佐賀県"=>"佐賀県",  "長崎県"=>"長崎県",  "熊本県"=>"熊本県",  "大分県"=>"大分県",
      "宮崎県"=>"宮崎県",  "鹿児島県"=>"鹿児島県",  "沖縄県"=>"沖縄県");
    $this->_form->addElement('select', 'area', '都道府県', $areaArray, 'id = area'); 
    // 住所
    $this->_form->addElement('text', 'place', '住所', array('id' => 'place', 'size' => 50, 'maxlength' => 50));
    $this->_form->addElement('text', 'place2', '番地・マンション名', array('id' => 'place2', 'size' => 50, 'maxlength' => 50));
    // 電話番号のグループ 
    $phoneArray[] = &HTML_QuickForm::createElement('text', 0, null, array('id' => 'phone0', 'size' => 10, 'maxlength' => 5));
    $phoneArray[] = &HTML_QuickForm::createElement('text', 1, null, array('id' => 'phone1', 'size' => 10, 'maxlength' => 5));
    $phoneArray[] = &HTML_QuickForm::createElement('text', 2, null, array('id' => 'phone2', 'size' => 10, 'maxlength' => 5));
    $this->_form->addGroup($phoneArray, 'phone', '電話番号', ' - ');
    // 性別のグループ 
    $sexArray[] = &HTML_QuickForm::createElement('radio', null, null, '女性', '女性');
    $sexArray[] = &HTML_QuickForm::createElement('radio', null, null, '男性', '男性');
    $this->_form->addGroup($sexArray, 'sex', '性別', ' ');
    // 開発言語のグループ 
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'c', null, 'C言語');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'vb', null, 'VB');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'php', null, 'PHP');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'perl', null, 'perl');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'ruby', null, 'ruby');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'python', null, 'python');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'java', null, 'java');
    $langArray[] = &HTML_QuickForm::createElement('checkbox', 'cobol', null, 'COBOL');
    $this->_form->addGroup($langArray, 'lang', '好きな間発言語', ' ');
    // テキストエリア
    $this->_form->addElement('textarea', 'content', 'お問い合わせ', array('id' => 'content', 'cols' => 60, 'rows' => 10));
  }

  // フォーム要素に検証ルールを追加
  function setRule() {
    // フィルターの適用 
    $this->_form->applyFilter('__ALL__','trim');
    // addRule
    $this->_form->addRule('name', 'お名前を入力してください', 'required', null, 'server');
    $this->_form->addRule('email', 'e-mailを入力してください', 'required', null, 'server');
    $this->_form->addRule('email', 'e-mailが不正です。半角英数字で入力してください', 'email', null, 'server');
    $this->_form->addRule('email2', 'e-mail確認を入力してください', 'required', null, 'server');
    $this->_form->addRule('email2', 'e-mail確認が不正です。半角英数字で入力してください', 'email', null, 'server');
    $this->_form->addRule(array('email','email2'), 'e-mailとe-mail確認が一致しません', 'compare', null, 'server');
    // addGroupRule
    $this->_form->addGroupRule('zip', '半角数字を入力してください', 'regex', '/^\d*$/', 'server');  // numeric 指定すると必須入力になります。
    $this->_form->addGroupRule('phone', '半角数字を入力してください', 'regex', '/^\d*$/', 'server');  // numeric 指定すると必須入力になります。
    $this->_form->addGroupRule('lang', '2つ以上選択してください', 'required', null, 2, 'server');  // howmany パラメータで入力個数を指定しています。
  }

  // 「確認」ボタン(入力画面)($argBtnName : ボタンの名前)
  function setSubmit($argBtnName) {
    $buttons[] = &HTML_QuickForm::createElement( 'submit', $argBtnName, '確認' ); 
    $this->_form->addGroup($buttons, "SUBMIT_BOTTONS", null, ' ');
  }

  // 「戻る」、「送信」ボタン(確認画面)($argRtnName: 「戻る」ボタンの名前、 $argSubmitName : 「送信」ボタンの名前)
  function setReturnSubmit($argRtnName, $argSubmitName) {
    $buttons[] = &HTML_QuickForm::createElement( 'submit', $argRtnName, '戻る' );
    $buttons[] = &HTML_QuickForm::createElement( 'submit', $argSubmitName, '送信' );
    $this->_form->addGroup($buttons, "SUBMIT_BOTTONS", null, ' ');
  }

  // 入力値を検証する
  function checkValidate() {
    return $this->_form->validate();
  }

  // 入力値を取得する  戻り値:要素名と入力された値の連想配列
  function getVals() {
    return $this->_form->exportValues();
  } 

  // 画面を表示する
  function dispForm() {
    $this->_form->display();
  }

  // 画面をフリーズする(確認画面、完了画面)
  function freezeForm() {
    $this->_form->freeze();
  }
}
?> 

thirdstep.php(実行ファイル)

文字化けを防ぐためエンコーディング指定しました。

<?php  // /var/www/html/fourthstep.php

  require_once "./FourthStepQuickForm.php";
  require_once "Smarty.class.php";

  $form = new FourthStepQuickForm('fourthstep.php');

  $form->setItem();   // 要素を追加
  $form->setRule();   // 検証ルール設定

  if ( isset($_POST['SUBMIT_BOTTONS']['SUBMIT_INDEX']) ) {
    // 確認画面表示
    // 検証実行
    if ($form->checkValidate()) {
      // 検証クリア時は「戻る」、「送信」ボタンを表示
      $form->setReturnSubmit('RETURN_CONF', 'SUBMIT_CONF');
      $form->freezeForm();    // 要素を凍結
    } else {
      $form->setSubmit('SUBMIT_INDEX');
    }
  } else {
    // 入力画面表示
    $form->setSubmit('SUBMIT_INDEX');
  }

mb_language('ja');  //"ja"にエンコー ディング
mb_internal_encoding("UTF-8");  //内部文字エンコーディングは"UTF-8"

  $smarty = new Smarty();

  $smarty->template_dir = '/var/www/private/Smarty_tpl/FourthStepQuickForm_tpl/templates/';
  $smarty->compile_dir  = '/var/www/private/Smarty_tpl/FourthStepQuickForm_tpl/templates_c/';
  $smarty->config_dir   = '/var/www/private/Smarty_tpl/FourthStepQuickForm_tpl/configs/';
  $smarty->cache_dir    = '/var/www/private/Smarty_tpl/FourthStepQuickForm_tpl/cache/';

  // renderer for Smarty templates の取得
  $renderer =& new HTML_QuickForm_Renderer_ArraySmarty($smarty);
  $renderer->setRequiredTemplate('{$label}{if $required}<span class="reqmark">*</span>{/if}');
  $renderer->setErrorTemplate('{if $error}<p class="error-message">{$error}</p>{/if}{$html}');
  $form->_form->accept($renderer);

  // 表示
  if ( isset($_POST['SUBMIT_BOTTONS']['SUBMIT_CONF']) ) {
    // 完了画面表示
    if ($form->checkValidate()) {
      $smarty->assign('value', $form->getVals());
      $smarty->display("submit.tpl");
    }
  } else {
    $smarty->assign('form', $renderer->toArray());
    $smarty->display("index.tpl");
  }
?>

index.tpl(フォーム表示テンプレート)

必須入力項目には自動的に*が表示されます。
checkbox と radio には要素ごとに <label> が自動的に付けられますが、その他の項目には <label> は付きません。テンプレートで書き足しています。

{* /var/www/private/Smarty_tpl/FourthStepQuickForm_tpl/templates/index.tpl *}
<!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" />
<title>Smarty + HTML_QuickForm サンプルフォーム</title>

<style type="text/css">
{literal}
body{ text-align:center;}
.content{ margin: 10px auto; width:700px;}
h1{ font-size: 1.2em; color:#336666;}
form{ text-align:left; border:1px dashed #999999; padding:20px;}
input{ font-size:1em;}
table{ border-collapse: collapse;}
th{ border:1px solid #999999; background-color:#dedede; color:#000000; font-weight:normal; padding:0.2em;}
td{ border:1px solid #999999; padding:0.2em;}
.reqnote{ font-size:0.8em; text-align:right;}
.reqmark{ color:#ff0000;}
.bottoms{ text-align:right;}
.message{ color:#ff0000;}
.error-message{ color:#ff0000; padding:0; margin:0;}
{/literal}
</style>

{$form.javascript} 
</head>
<body>
<div class="content">

  <h1>サンプルフォーム4</h1>
  <form {$form.attributes}>
    <p class="reqnote">{$form.requirednote}</p>
    
    <table>
      <tr>
        <th><label for="name">{$form.name.label}</label></th>
        <td>{$form.name.html}</td>
      </tr>
      <tr>
        <th><label for="namekana">{$form.namekana.label}</label></th>
        <td>{$form.namekana.html}</td>
      </tr>
      <tr>
        <th><label for="email">{$form.email.label}</label></th>
        <td>{$form.email.html}</td>
      </tr>
      <tr>
        <th><label for="email2">{$form.email2.label}</label></th>
        <td>{$form.email2.html}</td>
      </tr>
      <tr>
        <th><label for="zip0">{$form.zip.label}</label></th>
        <td>{$form.zip.html}</td>
      </tr>
      <tr>
        <th><label for="area">{$form.area.label}</label></th>
        <td>{$form.area.html}</td>
      </tr>
      <tr>
        <th><label for="place">{$form.place.label}</label></th>
        <td>{$form.place.html}</td>
      </tr>
      <tr>
        <th><label for="place2">{$form.place2.label}</label></th>
        <td>{$form.place2.html}</td>
      </tr>
      <tr>
        <th><label for="phone0">{$form.phone.label}</label></th>
        <td>{$form.phone.html}</td>
      </tr>
      <tr>
        <th>{$form.sex.label}</th>
        <td>{$form.sex.html}</td>
      </tr>
      <tr>
        <th>{$form.lang.label}</th>
        <td>{$form.lang.html}</td>
      </tr>
      <tr>
        <th><label>{$form.content.label}</label></th>
        <td>{$form.content.html}</td>
      </tr>
    </table>
    <p class="bottoms">{$form.SUBMIT_BOTTONS.html}</p>
  </form>
</div>
</body>
</html>

submit.tpl(送信完了表示テンプレート)

{* /var/www/private/Smarty_tpl/FourthStepQuickForm_tpl/templates/submit.tpl *}
<!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" />
<title>Smarty + HTML_QuickForm サンプルフォーム</title>

<style type="text/css">
{literal}
body{ text-align:center;}
.content{ margin: 10px auto; width:700px;}
h1{ font-size: 1.2em; color:#336666;}
.welcome{ text-align:left; border:1px dashed #999999; padding:20px;}
.reqnote{ font-size:0.8em; text-align:right;}
.bottoms{ text-align:right;}
.message{ color:#ff0000;}
{/literal}
</style>

</head>
<body>
<div class="content">
<h1>サンプルフォーム4 送信完了</h1>
<div class="welcome">
<p>こんにちは、{$value.name}({$value.namekana})さん。<br />ようこそ QuickForm の世界へ!</p>
<p>あなたのe-mailは『{$value.email}』ですね。</p>
<p>あなたの郵便番号は『{$value.zip[0]}-{$value.zip[1]}』ですね。</p>
<p>あなたのお住まいは『{$value.area} {$value.place} {$value.place2}』ですね。</p>
<p>あなたの電話番号は『{$value.phone[0]}-{$value.phone[1]}-{$value.phone[2]}』ですね。</p>
<p>あなたの性別は『{$value.sex}』ですね。</p>
<p>あなたのお好きな言語は『
{foreach from=$value.lang item=itemval key=keyname}
{$keyname}、
{/foreach}
 』ですね。</p>
<hr />
<p>{$value.content}</p>
</div>

</div>
</body>
</html>

まとめ

表示結果

投稿日:

ページのトップへ戻る