ActionFromからtemplateを生成するプラグイン(β)

しばらくご無沙汰してました。
で、いきなり本題ですが、ActionFromを定義したら、templateファイルくらいは自動で生成してほしいと思いませんか?
そんなものぐさなあなたに送るプラグインです:)


以下ではプラグインをインストールした場合の動作について説明します。
プラグインのダウンロード先とインストール方法は最後に記載してます。
素のEthnaの挙動では無いので勘違いしないようにしてください。

概要

このプラグインを導入すると、ActionFormに定義した内容でtemplateファイルを出力することができるようになります。

使い方

1. actionの作成

例として、ユーザがプロフィールを入力する画面を想定します。入力項目は「姓」「名」「ニックネーム」「性別」にします。
まずはいつも通りの手順でアクションを作成します。

ethna add-action profile_add
ethna add-action profile_add_do

user_addがフォームを表示するactionで、user_add_doが入力値を受け取るactionになることを想定しています。

2. ActionFormの編集。

いつも通りの手順でuser_add_doを編集して、フォームから受け取る値を定義します。
ここでは以下のようなActionFormを定義します。

<?php
class APPID_Form_ProfileAddDo extends APPID_ActionForm
{
    var $form = array(
        'lastname' => array(
            'name'          => '',
            'required'      => true,
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_TEXT,
        ),
        'firstname' => array(
            'name'          => '',
            'required'      => true,
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_TEXT
        ),
        'nickname' => array(
            'name'          => 'ニックネーム',
            'required'      => true,
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_TEXT,
        ),
        'sex' => array(
            'name'          => '性別',
            'required'      => true,
            'type'          => VAR_TYPE_INT,
            'form_type'     => FORM_TYPE_RADIO,
            'option'        => array(1 => '', 2 => ''),
        ),
   );
}
class APPID_Action_ProfileAddDo extends APPID_ActionClass
{
    function prepare()
    {
        if ($this->af->validate() > 0) {
            return 'profile_add';
        }
        return null;
    }
}
?>
3. プラグインの実行

これでプラグインを実行する準備は完了しました。templateファイルを自動で生成する為に以下のコマンドを実行してください。
第一引数はプラグイン名、第二引数がターゲットとなるテンプレート名、第三引数が先ほど作成したActionFormのアクション名になります。

ethna build-form profile_add_do profile_add

以上で完了です。

4. 動作確認

ブラウザからprofile_addにアクセスすると、以下の画面が表示されます。これはプラグインによって自動生成されたページです。

バリデーションでエラーが発生した場合は、以下の画面が表示されます。

で、何が起きたの?

このプラグインを実行すると、user_add_doのActionFormに設定された内容で、user_addのtemplateを出力します。
出力されたテンプレートファイルは以下の様になります(抜粋)

    <body>
        <h1>profile_add</h1>
        <div class="buildform">

            {if count($errors)}
            <div class="errors">
                <p><em>Oops... the following errors were encountered:</em></p>
                <ul>
                {foreach from=$errors item=error}
                    <li>{$error}</li>
                {/foreach}
                </ul>
            </div>
            {/if}
            {form ethna_action="profile_add_do"}
            <fieldset>
                <legend>profile_add_do</legend>
                <div class="row">
                {if is_error('lastname')}
                    <label for="lastname" class="error key">{form_name name="lastname"}<em>*</em></label>
                    {form_input name="lastname" id="lastname" class="error"}
                {else}
                    <label for="lastname" class="key">{form_name name="lastname"}<em>*</em></label>
                    {form_input name="lastname" id="lastname"}
                {/if}
                </div>
                <div class="row">
                {if is_error('firstname')}
                    <label for="firstname" class="error key">{form_name name="firstname"}<em>*</em></label>
                    {form_input name="firstname" id="firstname" class="error"}
                {else}
                    <label for="firstname" class="key">{form_name name="firstname"}<em>*</em></label>
                    {form_input name="firstname" id="firstname"}
                {/if}
                </div>
                <div class="row">
                {if is_error('nickname')}
                    <label for="nickname" class="error key">{form_name name="nickname"}<em>*</em></label>
                    {form_input name="nickname" id="nickname" class="error"}
                {else}
                    <label for="nickname" class="key">{form_name name="nickname"}<em>*</em></label>
                    {form_input name="nickname" id="nickname"}
                {/if}
                </div>
                <div class="row">
                {if is_error('sex')}
                    <label for="sex" class="error key">{form_name name="sex"}<em>*</em></label>
                    {form_input name="sex" id="sex" class="error"}
                {else}
                    <label for="sex" class="key">{form_name name="sex"}<em>*</em></label>
                    {form_input name="sex" id="sex"}
                {/if}
                </div>
            <div class="buttonrow">
            {form_submit value="OK"}
            </div>
            </fieldset>
            {/form}
        </div>
    </body>

ケルトンファイルを編集するには

phpテンプレートなので、phpで記述してください。skelファイル名はbuild.form.tplです。
テンプレート内では以下の値が使用できます。

$formActionFormの内容(array)中身はvar_dump()してください:)
$macro内部値(array)中身は(以下略
プロジェクト固有のスケルトンファイルはプロジェクトのトップディレクトリ配下にあるskelディレクトリに配置することが出来ます。

先生!生成したコードが意味不明です

現状のプラグインに含まれるテンプレートは、エラーの項目に色を付けたりlabelを張ったりしてるので、わかりにくいかもしれません。
というわけで、まずはテンプレートをシンプルにしてみましょう。おおよそこんな感じになります。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $macro['client_enc']; ?>">
    </head>
    <body>
        <h1><?php echo $macro['action_name']; ?></h1>
        {if count($errors)}
        <ul>
            {foreach from=$errors item=error}
            <li>{$error}</li>
            {/foreach}
        </ul>
        {/if}
<?php foreach($form as $action_name => $defs): ?>
        {form ethan_action="<?php echo $action_name; ?>"}
        <table>
<?php foreach($defs as $key => $def): ?>
            <tr>
                <th>{form_name name="<?php echo $key; ?>"}</th>
                <td>{form_input name="<?php echo $key; ?>"}</td>
            </tr>
<?php endforeach; ?>
        </table>
        {form_submit value="OK"}
        {/form}
<?php endforeach; ?>
    </body>
</html>

プラグインを通して出力されるコードは以下の様になります。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <h1>profile_add</h1>
        {if count($errors)}
        <ul>
            {foreach from=$errors item=error}
            <li>{$error}</li>
            {/foreach}
        </ul>
        {/if}
        {form ethan_action="profile_add_do"}
        <table>
            <tr>
                <th>{form_name name="lastname"}</th>
                <td>{form_input name="lastname"}</td>
            </tr>
            <tr>
                <th>{form_name name="firstname"}</th>
                <td>{form_input name="firstname"}</td>
            </tr>
            <tr>
                <th>{form_name name="nickname"}</th>
                <td>{form_input name="nickname"}</td>
            </tr>
            <tr>
                <th>{form_name name="sex"}</th>
                <td>{form_input name="sex"}</td>
            </tr>
        </table>
        {form_submit value="OK"}
        {/form}
    </body>
</html>

残念な話

ActionFormでrequiredの値が変更になった場合は、再生成する必要があります。理由はテンプレートファイルの生成時にrequiredの項目に「*」をつけているからです。



この問題を解決するにはrequiredの値を取得するsmarty_function_form_required()的なフォームヘルパを作成してtemplateからrequiredの値を取得すれば良いのでしょうが、そこまでは手をつけていません。

「*」が必要なければ、スケルトンファイルから該当箇所を削除してください。



イイワケをすると、method(GET/POST)の指定とか、enctypeとか、入力ヒントとか、フォーム名(例えば"請求フォーム"とかの和名) とかがActionFormで設定できて、それがtemplateにも反映されたり、templateファイルが存在しない場合は都度自動で生成できたり、いろいろムニャムニャできた方が幸せになれるかなーとは思うのですが、改造しまくってデフォのEthnaから離れすぎるのもどうよ、と思って区切りのいいところでやめました:)

その他

ActionFormのテンプレートも通常通り利用可能です。

既存のアプリケーションに与える影響

テンプレートファイルを出力するだけなので、既存のアプリケーションへの影響はありません。

ダウンロード

2.5.0のpreview2で確認してます。PHP5でしかテストしていません。PHP4で動作したら教えてください:)

ダウンロードEthna_Plubin_BuildForm-0.0.tzg

インストール

ダウンロードしたファイルをEthnaをインストールした先のディレクトリで展開してください。

既知のバグ

  • 引数のアクション名・テンプレート名が複数指定できてしまいます。有効なのは先頭の2つです。

ToDo

  • オプションのテストをほとんどやってないのでやる
  • バグ修正