肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

アクションフォームにデフォルト値を与える(フォームヘルパ)

$form = array (   
        'start' =>   array(   
            'form_type'     =>   FORM_TYPE_TEXT, // フォーム型   
            'default'       =>   'なんとか',   
        ),  

ただ、こう書いた場合には、’なんとか’みたいに単純な文字列ならいいんですが、phpの変数、関数が使えません。

これは結構不便です。という訳で、それを回避するためには実は基本的なEthnaの関数の$this->af->set(2)を使って、prepareメソッド内、もしくはテンプレートを呼び出す前にこんな風に書くとphpの変数や関数などが使えますよ。

$this->af->set('start',date("Y/m/d"));  // 関数もこんな感じで。
http://gmaccess.jmj.at/2007/11/28/ethna%e4%bf%ae%e8%a1%8c%e6%97%a5%e8%a8%982/

私も、今の日付時間なんかを表示したいなーってときに定義に含めることができなくてちょっと悩んだことがありました。
Ethnaは割りと自由なので色々やり方があると思いますが、せっかくだから例も出しとくです。


(なんでツッコミいれようと思ったか書くの忘れてたから追記しとく 11/30)

$this->af->set() してしまうと

実はユーザの入力を保持することができなくなります。
いや、厳密に言えば、「if で値がセットされていればdefault値はセットしない」という処理を加えればできなくもないですが、それではせっかくのフレームワークでフォームヘルパを使う利点が失われてしまいます。
できれば、

  • 指定してFormにユーザからの値がPOST(またはGET)されていなければ、defaultを表示
  • ユーザからの値があれば、それを表示

という挙動にしたいものです。

というわけで、defaultに値をセットしておけばそれが実現されるであろう*1という前提で、その方法をいくつか例示します。

(追記ここまで)

prepare内で定義

<?php
...
    function prepare()
    {
        $this->af->form['date']['default'] = date("Y-m-d H:i:s");
        return null;
    }

みたいに、ActionFormのformメンバのdefaultに直接代入してあげちゃったりもできます。この辺は、defaultに限らず、「DBから取得してきたレコードの内容をselectのoptionにしたい」みたいな場合にも使えます。
こういう使い方は、Ethna×PHP本の第五章でhaltさんが使ってました。

テンプレートに直接記述して定義

これは、dateのような、Smartyに関数が用意してあったりする場合に使える方法です。

{form_input name="date" default=$smarty.now|date_format:"%Y-%m-%d %T" }

こんな方法も使える。$smarty.nowは、現在のタイムスタンプを取得するSmarty関数で、date_formatは日付表示の形式を整える修飾子(modifier)す。

もちろん、別に関数じゃなくても、

{form_input name="date" default="デフォルトの文字列" }

と定義しても認識されます。

defaultを使うときの注意点

(追記2008/1/3) この問題では、Revision 489で修正されました。ただし、まだリリースされてませんので、2.3.2で使いたい方は下記のようにSmartyPluginを修正してください。


Ethnaのフォームヘルパでdefaultを使って定義した場合、その値を書き換えてポストした後、エラーなどで同じページに遷移してきたとき、書き換えてポストした値は、defaultで上書きされて戻されてしまいます

この挙動はちょっとおかしくないかい?と思ってるのですが、「仕様ですか?それとも意図しない挙動ですか?」と、以前MLに投げたけど無反応だったよ><

ポスト時にはユーザの入力を保持しつつ、フォームヘルパのdefaultを使う場合、Ethna_SmartyPlugin.phpsmarty_function_form_inputを修正します。

修正前

<?php
...
    // default
    if (isset($params['default'])) {
        // {form_input default=...}が指定されていればそのまま

    } else if (isset($block_params['default'])) {
        // 外側の {form default=...} ブロック
        if (isset($block_params['default'][$name])) {
            $params['default'] = $block_params['default'][$name];
        }
    } else {
        // 現在のアクションで受け取ったフォーム値
        $af =& $c->getActionForm();
        $val = $af->get($name);
        if ($val !== null) {
            $params['default'] = $val;
        }
    }

修正後

<?php
...
    // default
    if (isset($params['default'])) {
        // {form_input default=...}が指定されていればそのまま

    } else if (isset($block_params['default'])) {
        // 外側の {form default=...} ブロック
        if (isset($block_params['default'][$name])) {
            $params['default'] = $block_params['default'][$name];
        }
    }
    
    // 現在のアクションで受け取ったフォーム値
    // ここが default の if の中に入ってたから挙動がおかしい
    $af =& $c->getActionForm();
    $val = $af->get($name);
    if ($val !== null) {
        $params['default'] = $val;
    }


ちなみに、patchあてられるのであれば、

--- Ethna_SmartyPlugin.php      2007-11-06 06:43:32.000000000 +0900
+++ Ethna_SmartyPlugin.071106.php  2007-11-06 06:43:16.000000000 +0900
@@ -718,12 +718,13 @@
         if (isset($block_params['default'][$name])) {
             $params['default'] = $block_params['default'][$name];
         }
-    } else {
-        // 現在のアクションで受け取ったフォーム値
-        $af =& $c->getActionForm();
-        $val = $af->get($name);
-        if ($val !== null) {
-        $params['default'] = $val;
+    }
+
+    // 現在のアクションで受け取ったフォーム値
+    $af =& $c->getActionForm();
+    $val = $af->get($name);
+    if ($val !== null) {
+        $params['value'] = $val;
     }

で修正できますです。

*1:正確にいうと、現時点でのEthna2.3.2では、これが実現されない。このわけは、「注意点」で。