Validation.

バリデーション機能を活用した簡易チェック画面の作成メモ.

実装したい内容

実装したい内容は以下の5つだけ(バンドル作成手順はスキップ).

・コントローラに初期表示とボタン押下処理

・レンダリングを行うForm処理

・単純明快なEntityクラスを実装

・画面デザイン

・validation.yml記載

初期表示とボタン押下処理の実装.

初期表示時はレンダリング処理のみ、ボタン押下時(POST)の場合はチェック実行.

namespace Symfony2Bundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony2Bundle\Form\Symfony2Type;
use Symfony2Bundle\Entity\Symfony2Entity;

class ScreenController extends Controller
{
    public function viewScreenAction()
    {
        $request = $this->getRequest();
        $success = "";   
        if ($request->getMethod() === 'POST') {

            $form = $this->createForm(
                    new Symfony2Type(), 
                    new Symfony2Entity(), 
                    array('validation_groups' => 'symfony2'));
            $form->handleRequest($request);

            if ($form->isValid()) {
                $success = "リクエストパラメータに問題はありません。";
            }
        } else {
            $form = $this->createForm(new Symfony2Type(), null);
        }
        return $this->render('Symfony2Bundle:Screen:viewScreen.html.twig', 
                            array("form" => $form->createView(), "success" => $success));
    }

}

Form処理

レンダリングを行うためのForm処理クラスの実装.

namespace Symfony2Bundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony2Bundle\Entity\Symfony2Entity;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class Symfony2Type extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('text1', 'text', array('required' => true, 'max_length' => 8));
        $builder->add('text2', 'text', array('required' => false));
        $builder->add('text3', 'text', array('required' => false));

        $builder->add('select', 'choice', array(
            'empty_value' => '選択してください',
            'choices' => array(
                Symfony2Entity::SELECT_TYPE1 => '男',
                Symfony2Entity::SELECT_TYPE2 => '女'
            ),
            'required' => false
        ));

        $builder->add('check', 'choice', array(
            'choices' => array(
                Symfony2Entity::CHECK_TYPE1 => '洋食派',
                Symfony2Entity::CHECK_TYPE2 => '和食派'
            ),
            'expanded' => true, 
            'multiple' => true,
        ));

        $builder->add('radio', 'choice', array(
            'choices' => array(
                Symfony2Entity::RADIO_TYPE1 => '醤油ラーメン',
                Symfony2Entity::RADIO_TYPE2 => 'とんこつラーメン'
            ),
            'expanded' => true, 
            'multiple' => false,
        ));
    }

    public function getName()
    {
        return 'Symfony2';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'csrf_protection' => false,
        ));
    }

}

バリデーションは後ほどyml中にも定義するが、テキスト1のみ桁数制限.

Entityクラス

今回はテキストフィールド3つ、セレクト、チェック、ラジオをそれぞれ1つずつ生成.

namespace Symfony2Bundle\Entity;

class Symfony2Entity
{

    CONST SELECT_TYPE1 = 1;
    CONST SELECT_TYPE2 = 2;
    CONST CHECK_TYPE1 = 1;
    CONST CHECK_TYPE2 = 2;
    CONST RADIO_TYPE1 = 1;
    CONST RADIO_TYPE2 = 2;

    private $text1;
    private $text2;
    private $text3;
    private $select;
    private $check;
    private $radio;

    public function setText1($text1)
    {
        $this->text1 = $text1;
    }

    public function getText1()
    {
        return $this->text1;
    }

    public function setText2($text2)
    {
        $this->text2 = $text2;
    }

    public function getText2()
    {
        return $this->text2;
    }

    public function setText3($text3)
    {
        $this->text3 = $text3;
    }

    public function getText3()
    {
        return $this->text3;
    }

    public function setSelect($select)
    {
        $this->select = $select;
    }

    public function getSelect()
    {
        return $this->select;
    }

    public function setCheck($check)
    {
        $this->check = $check;
    }

    public function getCheck()
    {
        return $this->check;
    }

    public function setRadio($radio)
    {
        $this->radio = $radio;
    }

    public function getRadio()
    {
        return $this->radio;
    }

}

画面デザイン

Symfony2でサポートされているtwigで作成.

{ % extends '::layout.html.twig' % }
{ % block main % }
<div id="testscreen">
    <form method="post" action="{ { path('symfony2_ViewScreen') } }">
        <h2>Symfony2サンプル画面</h2>
        { % if info is defined and info is not null % }
        <div>
        { % else % }
        <div class="hidden-block">
        { % endif % }
            <ul>
                <li class="successalert">{ {success} }</li>
            </ul>
        </div>
        { % if not form.vars.valid % }
        <div>
        { % else % }
        <div class="hidden-block">
        { % endif % }
            <div class="erroralert">
            { { form_errors(form) } }
            { % for children in form.children % }
                { % if not children.vars.valid % }
                    { { form_errors(children) } }
                { % endif % }
            { % endfor % }                                    
            </div>
        </div>
        <div>
            { { form_label(form.text1, 'テキスト欄①:', {'label_attr' : {'class': 'middle'} }) } }
            { { form_widget(form.text1, { 'attr': {'class': 'form-control'}})}}
        </div>
        <div>
            { { form_label(form.text2, 'テキスト欄②:', {'label_attr' : {'class': 'middle'} }) } }
            { { form_widget(form.text2, { 'attr': {'class': 'form-control'}})}}
        </div>
        <div>
            { { form_label(form.text3, 'テキスト欄③:', {'label_attr' : {'class': 'middle'} }) } }
            { { form_widget(form.text3, { 'attr': {'class': 'form-control'}})}}
        </div>
        <div>
            { { form_label(form.select, 'セレクト欄:', {'label_attr' : {'class': 'middle'} }) } }
            { { form_widget(form.select, { 'attr': {'class': 'form-control'}})}}
        </div>
        <div>
            { { form_label(form.check, 'チェック欄:', {'label_attr' : {'class': 'middle'} }) } }
            { % for checkChildren in form.check % }
                <label>
                    { { form_widget(checkChildren) } }
                    { { checkChildren.vars.label } }
                </label>
            { % endfor % }
        </div>
        <div>
            { { form_label(form.radio, 'ラジオ欄:', {'label_attr' : {'class': 'middle'} }) } }
            { % for checkChildren in form.radio % }
                 <label>
                    { { form_widget(checkChildren) } }
                    { { checkChildren.vars.label } }
                </label>
            { % endfor % }
        </div>
        <div>
            <button type="submit" name="regist" id="regist"> CHECK </button>
        </div>

</div>
{ % endblock % }
</div></form></div>

バリデーション定義

最後にvalidation.ymlの定義.

Symfony2Bundle\Entity\Symfony2Entity:
    properties:
        text1:
            - Regex:
                pattern: "/\A[1-3]{1}\z/"
                match:  true
                message: "テキスト1は1~3の範囲でご指定下さい。"
                groups: ["symfony2"]
        text2:
            - NotBlank:
                message: "テキスト2を入力してください。"
                groups: ["symfony2"]

作った画面を動かしてみる

作った画面イメージはこんな感じ↓↓↓

チェックエラーの場合はエラー内容が全て画面表示.

チェックに問題がない場合はリクエストパラメータに問題がない旨のメッセージが出力.

複雑なチェックはカスタムバリデーション等で対応可能なので割りと楽.

Fin.