読者です 読者をやめる 読者になる 読者になる

orangain flavor

じっくりコトコト煮込んだみかん2。知らないことを知りたい。

Zend_Form をデザイナに優しい形でレンダリングする方法

Zend_Formのクイックスタートにあるフォームのレンダリングの節を読むと、フォームのレンダリング

<?php echo $form->render($view); ?>

または

<?php echo $form; ?>

によって行い、表示のカスタマイズはデコレータで行うと書いてあります。

この方法は確かにスマートですし、デコレータを駆使することで表示を一括変更したいときに全体での変更が少なくて済むという利点があります。しかし、デコレータによるカスタマイズは、プログラムがよくわかっている人でないと難しいですし、1箇所だけ別の表示をしたいというときにわざわざ新しいデコレータを作らなくてはいけないという欠点があります。

このため、ここでは情報の少ない「<?php echo ?>を用いてHTMLの中に1つずつ入力フォームをレンダリングする方法」を解説します。

フォームの定義

<?php
class My_Form_Comment extends Zend_Form {
  public function init() {
    $this->addElement('text', 'name', array(
      'required' => false, 
      'label' => '名前',
      'description' => '入力しなくても構いません',
      'validators' => array(
        array('stringLength', false, array('max' => 100, 'encoding' => 'utf-8')),
      ),
    ));
    $this->addElement('textarea', 'comment', array(
      'required' => true, 
      'label' => 'コメント',
      'cols' => 45, 
      'rows' => 5,
      'validators' => array(
        array('stringLength', false, array('max' => 5000, 'encoding' => 'utf-8')),
      ),
    ));
    $this->setElementDecorators(array(
      'Label',
      'Errors',
      'ViewHelper',
      'Description',
    ));
  }
  
  public function setView($view) {
    parent::setView($view);
    
    // renderメソッドを使う場合と異なり、自分で設定する必要がある
    foreach ($this->getElements() as $element)
    {
      $element->setView($this->getView());
    }
  }
}
?>

テンプレート (template.php) のフォーム周り

<form method="post" action="">
  <dl>
    <dt><?php echo $form->name->renderLabel() ?></dt>
    <dd>
      <?php echo $form->name->renderErrors() ?>
      <?php echo $form->name->renderViewHelper() ?>
      <?php echo $form->name->renderDescription() ?>
    </dd>
    <dt><?php echo $form->comment->renderLabel() ?></dt>
    <dd>
      <?php echo $form->comment->renderErrors() ?>
      <?php echo $form->comment->renderViewHelper() ?>
      <?php echo $form->comment->renderDescription() ?>
    </dd>
  </dl>
  <input type="submit"/>
</form>

これらを使って、以下のようにすることで、フォームをレンダリングできます。

<?php
// 適宜require等

$form = new My_Form_Comment();
$form->setView(new Zend_View());

if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
  if ($form->isValid($_POST))
  {
    // do something
    return;
  }
}

require('template.php');
?>

POSTしたときのレンダリング結果は次のようになります。(読みやすいよう整形しています)

<form method="post" action="">
  <dl>
    <dt><label for="name" class="optional">名前</label></dt>
    <dd>           
      <input type="text" name="name" id="name" value="">      
      <p class="hint">入力しなくても構いません</p>
    </dd>
    <dt><label for="comment" class="required">コメント</label></dt>
    <dd>
      <ul class="errors"><li>Value is required and can't be empty</li></ul>      
      <textarea name="comment" id="comment" cols="45" rows="5"></textarea>
    </dd>
  </dl>

  <input type="submit"/>
</form>

見てわかるようにメソッドと出力の関連は次の通りです。

renderLabel
<label>タグ。required属性により、optionalまたはrequiredというクラスがつく。
renderErros
<ul class="errors">タグ。エラーがないときには<ul>自体が出力されない。
renderViewHelper
入力フォーム要素。
renderDescription
<p class="hint">タグ。デフォルトは<p>タグだが変更可能。


このようにすることで、HTMLをちょこっと修正したい場合に、簡単に修正することが可能になります。


※この記事は、Zend Framework 1.10.4に基づいています。