somemo's diary

プログラマ、雑記、プログラミング関係はLinkから、数式はこっちでまとめていることが多い

【Zendframework】Guestbookの登録とフォーム

前回作成したGuestbookの登録用フォームを作成し、そのアクションとビューを作成します。

フォームの作成

zend_toolを使用して、下記コマンドを実行しフォームを作成します。

zf.bat create form Guestbook

.zfproject.xmlにformの要素が追加されます。

<formsDirectory>
  <formFile formName="Guestbook"/>
</formsDirectory>
<layoutsDirectory enabled="false"/>

application\formsに作成されたGuestbook.phpを以下のように修正します。

<?php
// application/forms/Guestbook.php

class Application_Form_Guestbook extends Zend_Form
{
    public function init()
    {
        // Set the method for the display form to POST
        $this->setMethod('post');

        // Add an email element
        $this->addElement('text', 'email', array(
            'label'      => 'Your email address:',
            'required'   => true,
            'filters'    => array('StringTrim'),
            'validators' => array(
                'EmailAddress',
            )
        ));

        // Add the comment element
        $this->addElement('textarea', 'comment', array(
            'label'      => 'Please Comment:',
            'required'   => true,
            'validators' => array(
                array('validator' => 'StringLength', 'options' => array(0, 20))
                )
        ));

        // Add a captcha
        $this->addElement('captcha', 'captcha', array(
            'label'      => 'Please enter the 5 letters displayed below:',
            'required'   => true,
            'captcha'    => array(
                'captcha' => 'Figlet',
                'wordLen' => 5,
                'timeout' => 300
            )
        ));

        // Add the submit button
        $this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Sign Guestbook',
        ));

        // And finally add some CSRF protection
        $this->addElement('hash', 'csrf', array(
            'ignore' => true,
        ));
    }
}

以下の要素を追加してあります。

  • メールアドレス用のテキストボックス
  • コメント用のテキストエリア
  • 投稿用の認証CAPTCHA
  • 送信ボタン
  • CSRF対策のトークン

アクションの作成

投稿したフォームを処理するために、GuestbookControllerにsignActionを追加します。下記コマンドを実行します。

zf.bat create action sign Guestbook

GuestbookControllerにsignAction、GuestbookControllerTestにtestSignAction、ビューとしてsign.phtmlが追加されています。

signActionを以下のように修正します。

public function signAction()
{
    $request = $this->getRequest();
    $form    = new Application_Form_Guestbook();

    if ($this->getRequest()->isPost()) {
        if ($form->isValid($request->getPost())) {
            $comment = new Application_Model_Guestbook($form->getValues());
            $mapper  = new Application_Model_GuestbookMapper();
            $mapper->save($comment);
            return $this->_helper->redirector('index');
        }
    }

    $this->view->form = $form;
}

まずリクエストオブジェクトを取得し、フォームオブジェクトを生成しています。

次に、リクエストメソッドがPOSTの場合、POSTされたデータをフォームオブジェクトに渡して入力チェックを行います。

正しい値がPOSTされていた場合、モデルにPOSTされたデータを渡しながら生成しています。

生成されたモデルをマッパーに渡してDBに登録後、indexにリダイレクトしています。

sign.phtmlを以下のように修正します。

<!-- application/views/scripts/guestbook/sign.phtml -->
 
Please use the form below to sign our guestbook!
 
<?php
$this->form->setAction($this->url());
echo $this->form;

フォームオブジェクトによって生成されたhtmlソースを確認していきます。

フォーム要素は以下のとおりです。メソッドがPOST指定され、action属性は、

<form enctype="application/x-www-form-urlencoded" method="post" action="/zend/public/guestbook/sign">

フォームクラスで設定したPOSTメソッド、ビューで設定したURL(helperのメソッド)がaction属性に設定されています。また、URLエンコードされるように明示的に設定されています。

フォーム内側の要素のソースは以下のようになっています。

<!--フォーム内の全要素を囲むdlタグ-->
<dl class="zend_form">

<!--フォーム内の各要素に設定されたラベルを囲むdtタグ-->
<dt id="email-label">

<!--フォーム内の各要素を囲むddタグ-->
<dd id="email-element">
  <input type="text" name="email" id="email" value="" />
  <ul class="errors">
    <li>Value is required and can't be empty</li>
  </ul>
</dd>

デコレータと呼ばれるformを装飾するものに囲まれています。正直邪魔・・・。ただし、これらを解除して自分の好きなように設定もできるようなので知識を増やせばいいかもしれないです。

また、エラーメッセージはulタグに囲まれています。このメッセージを日本語にもできるようです。

投稿用の認証CAPTCHA?は以下のようになっています。

<pre>
   _____   _    _               _____     _____   
  / ___// | || | ||     ___    |  ___||  / ____|| 
  \___ \\ | || | ||    /   ||  | ||__   / //---`' 
  /    // | \\_/ ||   | [] ||  | ||__   \ \\___   
 /____//   \____//     \__ ||  |_____||  \_____|| 
`-----`     `---`       -|_||  `-----`    `----`  
                         `-`                      
</pre>
<input type="hidden" name="captcha[id]" value="8050cbdeb1d4ff1cb3a51fa52fca1754" id="captcha-id" />
<input type="text" name="captcha[input]" id="captcha-input" value="" />

他の要素と違い、captcha[id]とcaptcha[input]に分かれています。

感想

フォームオブジェクトと、フォームに対する入力チェック(validation)があることはとてもいいなと思いました。データの管理をフォームオブジェクトに任せることができ、入力チェックをコントローラ部分に同じことを書かなくてすみます。

このサンプルでは登録しかないので分からないのですが、編集を行うときにあるフォームは入力しなくなるといった場合に対応できるのかが気になるところです。

参考