2006年10月13日の投稿

2006-10-13
晴れ

QuickForm + Template_Flexy で動的フォームを作るのに悩む

ゆりこ による 00:02:12 の投稿
カテゴリー: ソフトウェア

Yuriko.Net は独自ウェブログシステムに移行しましたが、運営者が使う管理画面はまだ完成していません;-) 記事の作成・編集、カテゴリーの追加・編集、イベントの追加・編集は可能ですが、それ以外のデーターは phpMyAdmin 経由で MySQL データーベースを直接いじっています。phpMyAdmin が優秀なので、自前の管理画面がなくてもウェブログの管理ができてしまうため、開発をあわてる必要がないのです;-)

開発が遅い理由の1つに、わたしの PEAR ライブラリーの理解が十分でないことがあります。とくに、HTML_QuickFormHTML_Template_Flexy を組み合わせる部分が悩みの種です。どちらも高機能なパッケージで使いこなすのが大変な上に、QuickForm で作ったフォーム部品のレンダリングを Flexy でやらせるという組み合わせ技になると、ドキュメントが非常に少なくて試行錯誤しています。

フォーム部品が固定の場合は使い方がなんとか分かりましたが、「記事一覧」のようにフォーム部品の数が変化する場合は完成していません。フォーム部品を描画させるところはできたのですが、フォームの入力内容を検証するルールの設定が分かりません。そのため、正当な値を入れた場合は先に進みますが、不正な値を入れた場合は処理がおかしくなってします。どうせ管理画面は自分だけが使うものなので、値の検証がええ加減でもいいわけですが、やはりきちんと作りたいものです。

フォーム部品を作る部分のコードは以下のような感じです (説明用に抜粋しています)。

$form = new HTML_QuickForm('ev-mod', 'post');
$rows = array($form->addGroup(array(), 0, NULL, NULL)); // add dummy
foreach ($list as $e) {
    $cols = array();
    if (year_of($e['date']) < 1900) {
        $e['date'] = '2000-01-01';
    }
    $end = $e['end'] ? $e['end'] : $e['date'];
    $cols[] = $form->createElement('static', 'target', NULL, $e['id']);
    $cols[] = $form->createElement('date', 'date', '', 
        array('language' => 'ja', 'format' => 'Y年m月d日', 
        'minYear' => year_of($e['date']) -5, 
        'maxYear' => year_of($e['date']) +5));
    $cols[] = $form->createElement('checkbox', 'has_end', NULL, 
        '終了日を設定');
    $cols[] = $form->createElement('date', 'end', '', 
        array('language' => 'ja', 'format' => 'Y年m月d日', 
        'minYear' => year_of($end) -5, 
        'maxYear' => year_of($end) +5));
    $cols[] = $form->createElement('textarea', 'desc', '説明', 
        array('cols' => 48, 'rows' => 3));
    $cols[1]->setValue($e['date']);
    $cols[2]->setValue(isset($e['end']));
    $cols[3]->setValue($end);
    $cols[4]->setValue($e['description']);
    $rows[] = $form->addGroup($cols, intval($e['id']), NULL, NULL);
}
$form->addGroup($rows, 'list', NULL, NULL);
$form->addElement('submit', 'back', '戻る');
$form->addElement('submit', 'modify', '修正する');
$rules = array();
foreach($rows as $id => $cols) {
    $rule[$id]['date'][] = array('開催日を入力してください。', 'required', NULL, 'server');
    $rule[$id]['desc'][] = array('説明を入力してください。', 'required', NULL, 'server');
    $rule[$id]['desc'][] = array('説明は512文字以内です。', 'maxlength', 512, 'server');
}
$form->addGroupRule('list', $rules);
$rend =& new HTML_QuickForm_Renderer_ObjectFlexy($page);
$form->accept($rend);
$page->mod_form = $rend->toObject();
$output = new HTML_Template_Flexy();
$output->compile('events.html');
$output->outputObject($page);

そしてテンプレート (events.html) の抜粋は次の通り。

{mod_form.outputHeader():h}
{mod_form.hidden:h}
<table class="list" border="1" cellspacing="0">
<caption>イベント修正</caption>
<thead>
  <tr><th>ID</th><th>開催日</th><th>終了日</th><th>説明</th></tr>
</thead>
<tbody>
<tr flexy:foreach="mod_form.list,id,e">
<td class="id">{id}</td>
<td class="mod-date">{e.date.html:h}
<div class="error" flexy:if="e.date.error">{e.date.error}</div></td>
<td class="mod-date">{e.has_end.html:h}<br />{e.end.html:h}
<div class="error" flexy:if="e.end.error">{e.end.error}</div></td>
<td class="desc">{e.desc.html:h}
<div class="error" flexy:if="e.desc.error">{e.desc.error}</div></td>
</tr>
</tbody>
</table>
<div class="error" flexy:if="mod_form.errors.list">
{mod_form.errors.list}</div>
<div>{mod_form.back.html:h} {mod_form.modify.html:h}</div>
</form>

addGroup を2重にすることで、テンプレートは作りやすくなりましたが、ルールが上手く動きません。addGroupRule でうまくいきそうなんですが、これでは動作していません。うーん困った。

なお、QuickForm でのクライアント側検証は使わない主義です;-) (続きはリンク先エントリに移設)

QuickForm のクライアント側検証はユーザビリティーが低い

ゆりこ による 11:38:37 の投稿
カテゴリー: ソフトウェア

(前エントリから移行)。わたしは、QuickForm でのクライアント側検証は使わない主義です;-) なぜなら、エラー表示がダイアログを出すいうユーザビリティーの低い仕組みだからです。エラー部分を直すためにはダイアログを閉じなければなりませんので、どこがエラーなのか記憶しておかなければなりません (サンプル)。

逆に、サーバー側検証は、不正な値のフォーム部品の真上/真下にエラー表示するという分かりやすいインターフェースになるので、こちらの方が親切です。クライアント側検証だとインターフェースが劣化してしまうのは、非常に問題です。PEAR 解説本ではクライアント側検証を勧めているようですが、現状の QuickForm が吐く JavaScript ではまるで勧められません;-)

将来、DOM をいじってフォームの真上/真下にエラー表示するという JavaScript を吐くようになれば、クライアント側検証をばりばり使ってもいいです。

動的フォームの検証は addFormRule でごまかす

ゆりこ による 14:44:37 の投稿
カテゴリー: ソフトウェア

動的に数が変更されるフォームの検証addFormRule でごまかすことにしました。これなら、foreach でループを回してしまえば検証が可能です。ただし、オブジェクト指向から外れたコードになってしまいます;-)

function check_mod_form($fields) {
    $errors = array();
    foreach ($fields['list'] as $id => $cols) {
        if (strlen($cols['desc']) < 1) {
            $errors['list'][$id]['desc'] = 
                '説明を入力してください。';
        }
        if (isset($cols['has_end']) && $cols['date'] >= $cols['end']) {
            $errors['list'][$id]['end'] = 
                '終了日は開催日より後にしてください。';
        }
    }
    return count($errors) ? $errors : TRUE;
}

なお、この場合、エラーメッセージが $this->mod_form->errors 以下に入ってしまい、テンプレート文法の都合で、エラーの出たフォーム部品の真下に表示させることができません。そこで、エラーメッセージを $this->mod_form->list 以下にコピーするというアドホックなコードも追加して解決しました;-)

$mod_rend =& new HTML_QuickForm_Renderer_ObjectFlexy($this);
$mod_form->accept($mod_rend);
$form_obj = $mod_rend->toObject();
// ----- Move error messages ----------
foreach ($form_obj->errors->list as $id => $e) {
	foreach ($e as $element => $msg) {
		$form_obj->list->$id->$element->error = $msg;
	}
}
$this->mod_form = $form_obj;

これで、フォーム検証の実行と、エラー表示を当該のフォーム部品の真下に表示させるという目的を果たせました。非常に泥臭くて、QuickForm のバージョンアップがあれば動かなくなりそうな危険なコードなので、本来の正しい方法は、さらに調査したいと思います。

今後の機能追加予定

ゆりこ による 17:04:11 の投稿
カテゴリー: 更新履歴

Yuriko.Net も、閲覧者からは他のウェブログとほぼ遜色ない状態になりましたが、よーく見ると不十分な点がいくつかあります。それらを追加するのが、今後の課題となるでしょう。

  • カテゴリーでの検索 (同一カテゴリーの記事をまとめて表示させる)
  • ページング機能 (1ページに記事が多い場合「次のページ」に分離する)
  • 本文の検索機能 (Google や Technorati に頼らない)
  • 最新のトラックバック・コメントの表示をつける。(そもそもフィードバックがないけど :-)
  • サイドバーに旅行ウェブログのヘッドラインを載せる。
  • トラックバック・コメントの RSS を提供
  • ケータイ向けサイトの復活

運営者向けの機能追加は、以下のようなものが残っています。

  • 記事投稿時に画像添付 (現状 SFTP で別途アップロード)
  • ケータイからの投稿機能
  • トラックバック・コメントの管理機能 (一覧表示だけはできる)
  • ヨソへのトラックバックの送信機能 (現在、トラバ送信は独立スクリプトを利用)
  • サイトの細かい設定をする機能 (1ページあたりの表示記事数の設定 etc)
  • スキンやモジュールの変更・追加機能
  • ユーザー登録機能
  • 登録ユーザーだけが見れる記事を作る機能
  • 複数ウェブログ運営機能

機能追加の構想はいっぱいあります。特に、登録ユーザーだけが見れる記事を作る機能は「ひみつ日記」を書くことができるという、珍しい仕組みになると思います。現状、mixi で「マイミクだけに見せる日記」を書いている人は多いと思いますが、それがウェブログツールでも可能になるとすればオモロイでしょう。

OpenPNE 試験運用

ゆりこ による 18:36:07 の投稿
カテゴリー: ふりひら,ソフトウェア

開店休業状態になっている「ふりひらML」ですが、SNS にリニューアルするべく、OpenPNEをインストールしてみました。インストールするには、設定ファイルをテキストエディタで少しいじったり、MySQL でデータベースを作ったりという細かい作業が必要でちょっと難しいですが、附属のドキュメントに従えば問題なく進められ、30分もかかりませんでした。

サイトのデザイン調整には時間がかかりそうですが、それができたら、現在の ML 登録者を招待して新生出発としたいです。

なにより感動したのが、性別欄の選択肢を自由に変更できることです!! ありきたりの「男性」「女性」だけじゃなく、それを変更したり、他の選択肢を追加したりができるのです。とりあえず「ないしょ」「たぶん女性」「おそらく男性」「男女不詳」の4項目にしてみましたが、もっといいのを追加した方がいいかも。

今年の年末コミケは29日〜31日なのかーー

ゆりこ による 19:12:31 の投稿
カテゴリー: 旅行

年末の予定を立てる上で、夜行列車の混雑状況を確認するために「コミックマーケット」の開催日を調べてみると、今年の年末は29日〜31日のようです。うぎゃーー。

ここ2年とも、大晦日にムーンライトながらで移動するというパターンにしていますが、この開催日だと大晦日出発のながらが満席で取れないという事態になりそうです。1月1日の JAL バーゲンフェアにするか、もっと早い日に帰省するかを考えないといけません。

iPod nano レッドリボン仕様

ゆりこ による 21:04:31 の投稿
カテゴリー: アップル・Macintosh

iPod nano (red) の写真
(写真は Apple の規定に基づいて使用しています)

アップルから、赤い iPod nano が登場しました。この赤色はタダの赤色ではなく、エイズ患者の支援運動におけるシンボルであるレッドリボンにちなんだ色なのです。まさにレッドリボン iPod と言えます。

商業製品とエイズ支援運動を結びつけるとは、なかなかできない芸当です。今度は、レインボー iPod とかも出ないかな〜〜。