MODx の eForm
を使うと、メールフォームが簡単につくれる。しかし、メールではなくてDB保存して、あとでまとめてデータを取得したいということもある。



<p>そういう用途にぴったりな eForm2db というのを見かけた。MODx が備える DBAPI と、eForm
のイベントハンドリングを使った、シンプルな snippet だ。こんなに簡単にできるのか、と喜んだのもつかの間、この snippet
を呼ぶと画面は真っ白、Apache のログにはエラー、DB には何も記録されない、という状態になった。</p>

<p>Apache のエラーログはこのような感じ。</p>

<pre class="prettyprint">
[Fri May 08 04:26:59 2009] [error] [client 10.1.1.231] PHP Fatal error: Call to
undefined function eForm2db() in /home/xxx/public_html/modx-0.9.6.3/assets
/snippets/eform/eform.inc.php on line 377, referer: http://test1.xxx.xxx/~xxx/modx/
</pre>

<p>試行錯誤の結果、snippet の呼び出しを [[snippet]] から [!snippet!]
に変えることで解決した。前者はキャッシュされた結果を用いるが、後者は snippet
をキャッシュせずに毎回実行する。たとえばログインsnippet
があって、未ログインの場合はログインフォームを、ログイン後はユーザー名を表示する場合には、キャッシュしてはいけないので後者を使う。</p>

ページに貼り付けるフォームはこんな感じ。フォーム chunk の直前に eForm2db の snippet
を置く。eFormOnBeforeMailSent で、メール送信前にイベント処理をする。

<pre class="prettyprint">
[!eForm2db!]

[!eForm? &formid=form1 &tpl=form1_tpl
&report=form1_report &thankyou=form1_thankyou
&to=xxx@xxx.xxx &from=xxx@xxx.xxx
&fromname=form1 &subject=form1
&eFormOnBeforeMailSent=eForm2db !]
</pre>

eForm2db snippet はこんな感じ。複数選択のチェックボックスは join で一つの文字列にまとめてみた。RDB
のテーブルは、MODx と同じ DB にあらかじめ作っておく。

<pre class="prettyprint">
function eForm2db( &$fields ) {
global $modx;

$dbTable = array();

$dbTable[email] = $fields[email];
$dbTable[checkbox1] = join(', ', $fields[checkbox1]);
$dbTable[hitokoto] = $fields[hitokoto];
$dbTable[postdate] = date( 'YmdHis', strtotime( $fields[postdate] ) );

$dbQuery = $modx->db->insert( $dbTable, 'form1' );

return true;
}
return '';
?>
</pre>