3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(PHP)Smarty利用時に入力チェックエラー時に入力画面に戻し入力データを再表示する方法

フォームの入力でチェックをした後どうするかについて、

 エラー画面に遷移しエラー表示→入力画面に戻す(戻るボタンで戻ってもらう)

という方法と、

 入力画面に戻しエラー表示

という2パターンがあると思います。

(まぁAjax使ってたりすると、JavaScript内でチェックかけてPHP側行く前の入力画面の段階でDOMを使ってエラー表示する方法ができるんですが。。。)

今回やろうとしてるのは後者の方法です。

なぜなら、前者だと作るのは楽ですが、ユーザビリティを考えると後者の方が利点があります。

しかし、ここで問題になってくるのが、入力画面に戻った時にユーザの入力内容をどう再表示するかということです。

とりあえず、入力チェックエラー後に、エラー画面ではなく入力画面を再表示する場合のSmartyテンプレートの書き方例 を参考にして書いてみました。

概要として、PDOを使ってSQLiteから表示項目を取得して入力ページを表示。入力チェックでNGなら、入力ページに戻し、エラーを表示するというものです。

session_start();

 

try {

// DBに接続する

$db = new PDO( 'sqlite2:./test.sqlite', '', '' );

/* ..... DBアクセス ..... */

//項目取得

$dbRes_product = $db->query( 'SELECT * FROM product ORDER BY id' )->fetchAll();

$dbRes_questionnaires = $db->query( 'SELECT * FROM questionnaires ORDER BY id' )->fetchAll();

// DBから切断する ( $db = null; も可能)

unset( $db );

} catch( PDOException $ex ) {

// DBアクセスができなかったとき

print 'アクセスできません : ' . $ex->getMessage();

unset( $db );

die();

}

//Smarty読み込み(ドキュメントルート外のSmartyクラスにアクセス)

require_once('./smarty/libs/Smarty.class.php');

//Smartyオブジェクト作成

$smarty = new Smarty();

//Smartyディレクトリ設定(キャッシュやテンプレート置き場など)

$smarty->template_dir = "./smarty/templates";

$smarty->compile_dir = "./smarty/templates_c";

$smarty->cache_dir ="./smarty/cache";

//エスケープ

$smarty->default_modifiers = array('escape','nl2br');

 

//$_SESSION['postdata']にユーザが入力したデータがあるのでそれをアサイ

if( isset($_SESSION['postdata'])){

$smarty->assign("q", $_SESSION['postdata'] );

}else{

$smarty->assign("q", array());

}

//エラー情報アサイ

if( isset($_SESSION['err_info'])){

$smarty->assign("err", $_SESSION['err_info'] );

}else{

$smarty->assign("err", array());

}

 

$smarty->assign("product", $dbRes_product);

$smarty->assign("questionnaires", $dbRes_questionnaires);

 

//テンプレート表示

$smarty->display("connect.tpl");

?>

method="post" action="confirm.php" >

氏名(必須):

{if isset($err.name)}

エラー:{$err.name}

{/if}

type="text" name="name" value="{if isset($q.name)}{$q.name}{else}氏名入力してください{/if}" >


製品(必須):

{if isset($err.product)}

エラー:{$err.product}

{/if}

{section name=iCnt loop=$product}

type="radio" name="product"

{if isset($q.product)

&& $q.product eq $product[iCnt].id}

checked="checked"

{/if}

value="{$product[iCnt].id}">{$product[iCnt].value}

{/section}



アンケート(必須。複数選択可):

{if isset($err.questionnaires)}

エラー:{$err.questionnaires}

{/if}

{section name=iCnt loop=$questionnaires}

type="checkbox" name="questionnaires[]"

{if isset($q.questionnaires)

&& is_array($q.questionnaires)

&& $questionnaires[iCnt].id|in_array:$q.questionnaires}

checked="checked"

{/if}

value="{$questionnaires[iCnt].id}">{$questionnaires[iCnt].value}

{/section}



type="submit" value="送信" name="submit">

(文字数制限のためハイライト無し)

session_start();

//入力チェック

InputCheck();

//okなら確認画面等に遷移。

function InputCheck(){

//セッション変数きれいに

unset($_SESSION['postdata']);

unset($_SESSION['err_info']);

//入力チェック処理

if( isset($_POST['name']) || empty($_POST['name']) ){

$errInfo['name'] = '氏名が指定されていません。';

}

if( ! isset($_POST['product']) ){

$errInfo['product'] = '項目が選択されていません。';

}

if( ! isset($_POST['questionnaires']) ){

$errInfo['questionnaires'] = '項目が選択されていません。';

}

if( count($errInfo) > 0 ){

//POSTデータ,エラー情報をセッション変数に持たす

$_SESSION['err_info'] = $errInfo;

$_SESSION['postdata'] = $_POST;

header("Location:input.php");

exit;

}

}

?>

ユーザが入力したフォームのデータをセッション変数に持たし、テンプレート内のIF文を使って、セッション変数が存在するならセットするというものですね。

テキストボックスなら、フォーム入力データを持つセッション変数内に存在すれば value にセットするだけです。

ラジオボタンは、ループ内で、データがフォーム入力データを持つセッション変数内に存在し、かつ value と同じ値ならチェックします。

複数選択できるチェックボックスは、ラジオボタンとほぼ同様ですが、is_array,in_array を使うのがみそです。

エラー情報も同様に、テンプレート内のIF文でデータがあれば表示します。

まぁたしかに、テンプレート内に条件分岐を入れるのは余りきれいなやり方ではないですが、それ以外にいい方法も思いつかなかったので。。。。