Help us understand the problem. What is going on with this article?

symfony validation処理の方法

More than 1 year has passed since last update.

はじめに

案件でとりあえずsymfony使い始めたけど、情報がまばらで苦労してます。
自分の復習や備忘録も兼ねてのsymfony記事です。
今回はvalidationについてまとめようと思います。

一個目のformの記事
http://qiita.com/yutaChaos/items/0ae0d1797db4cb16466c

環境

  • symgony 2.8
  • php 7.0

validationについて

  • symfonyでのvalidationは大きく分けて2つあります。(僕が現時点で知っているやつですが)
    • entityに直接記述する
    • FormTypeに記述する

entityに直接記述する方法

今回使用するentityの基本コードはこれです。

ToDo.php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * ToDo
 *
 * @ORM\Table(name="to_do")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ToDoRepository")
 */
class ToDo
{

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="task", type="integer", length=1)
     */
    private $task;

    /**
     * @var string
     * @Assert\NotBlank()
     * @Assert\Length(min = 2,max = 255)
     * @ORM\Column(name="memo", type="string", length=255, nullable=true)
     */
    private $memo;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="r_datetime", type="datetime", nullable=true)
     */
    private $rDatetime;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="u_datetime", type="datetime", nullable=true)
     */
    private $uDatetime;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set task
     *
     * @param string $task
     * @return ToDo
     */
    public function setTask($task)
    {
        $this->task = $task;

        return $this;
    }

    /**
     * Get task
     *
     * @return string 
     */
    public function getTask()
    {
        return $this->task;
    }

    /**
     * Set memo
     *
     * @param string $memo
     * @return ToDo
     */
    public function setMemo($memo)
    {
        $this->memo = $memo;

        return $this;
    }

    /**
     * Get memo
     *
     * @return string 
     */
    public function getMemo()
    {
        return $this->memo;
    }

    /**
     * Set rDatetime
     *
     * @param \DateTime $rDatetime
     * @return ToDo
     */
    public function setRDatetime($rDatetime)
    {
        $this->rDatetime = $rDatetime;

        return $this;
    }

    /**
     * Get rDatetime
     *
     * @return \DateTime
     */
    public function getRDatetime()
    {
        return $this->rDatetime;
    }

    /**
     * Set uDatetime
     *
     * @param \DateTime $uDatetime
     * @return ToDo
     */
    public function setUDatetime($uDatetime)
    {
        $this->uDatetime = $uDatetime;

        return $this;
    }

    /**
     * Get uDatetime
     *
     * @return \DateTime
     */
    public function getUDatetime()
    {
        return $this->uDatetime;
    }

    /**
     * @ORM\PrePersist
     */
    public function refreshRDatetime()
    {
        $this->setRDatetime(new \Datetime());
    }

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function refreshUDatetime()
    {
        $this->setUDatetime(new \Datetime());
    }

}
  • $memoにNotBlankとLengthの制約をかけるためにannotationを付与しています。 これだけです。めっちゃ簡単。optionを設定する場合は @Assert\Length(min = 2,max = 50)のように引数に値を付与すれば設定ができます。
    /**
     * @var string
     * @Assert\NotBlank()
     * @Assert\Length(min = 2,max = 255)
     * @ORM\Column(name="memo", type="string", length=255, nullable=true)
     */
    private $memo;

FormTypeに記述する

次にFormTypeに記載する場合です。

ToDoType

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type as InputType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;

class ToDoType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('task',
                InputType\ChoiceType::class,
                [
                    'choices' => [
                        '1' => 'work',
                        '2' => 'hobby'
                    ],

                    'constraints' =>
                        [
                            new Assert\NotBlank()
                        ]
                ]
            )
            ->add('memo',
                InputType\TextareaType::class,
                [
                    'constraints' => [
                        new Assert\NotBlank(),
                        new Assert\Length(['min' => 2, 'max' => 255])
                    ]
                ]);

        $entity = $builder->getData();

        if(!$entity->getId()){
            $builder->add('Create', InputType\SubmitType::class,
                [
                    'attr' => [
                        'class' => 'btn btn-primary'
                    ]
                ]
            );
        }else{
            $builder->add('Edit', InputType\SubmitType::class,
            [
            'attr' => [
                'class' => 'btn btn-primary'
            ]
                ]
            );
        }
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\ToDo'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_todo';
    }


}

ここではentityと同じvalidationルール(NotBlank,Length)を書いています。
add関数は第1引数がentityのメンバーの名前、第2引数はそのメンバーで利用したいフォームの種類、そして第3引数にはoptionが設定できます。
Entityと同様のvalidationはFormTypeでのvalidationは第三引数に配列キーをconstraintsで渡すことで設定できます。
ただEntityに記載する場合と異なるのが、FormTypeは実際に生成されるFormの情報を記載しているので、
制約だけではなく、入力フォームの種類も記載できます。
第二引数ではTextareaTypeを渡していますが、この情報を持ったFormを実際に表示するとtestareaのフォームが表示されます。
それだけではなく、formの種類に寄ったvalidationも自動的に付与されます。
例えば NumberTypeをフォームの種類を設定した場合は数字以外を弾くvalidationが設定されます。
FormTypeで規定する場合は適切なFormの種類を設定した上でconstraintsを設定することを考えると幸せになれると思います。
(前にTextTypeにGreaterThanを設定したら、普通の文字列がvalidationで弾かれなくて汗かいた)

http://symfony.com/doc/current/reference/constraints/GreaterThan.html

->add('memo',
InputType\TextareaType::class,
[
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(['min' => 2, 'max' => 255])
]
])

終わりに

symfonyには強力なvalidation機能が備わっていて、標準のvalidationでも結構いろいろなことができます。
さらに自分でカスタムvalidationを作成して、付与することが出来ます。
entityでもvalidation書けるけど、やっぱりEntityはデータ構造や付随する情報ぐらいにとどめて、実際のvalidationはFormTypeに任せた方がいいかなーと現時点では思っています。
(Best Practice読んでもValidation周りはよくわからんかった。。。)

参考

http://symfony.com/doc/current/reference/constraints.html
http://symfony.com/doc/current/reference/forms/types.html
http://symfony.com/doc/current/form/events.html

yutachaos
Programmer,Bassist,Bibliomania
recruitmp
結婚・カーライフ・進学の情報サイトや『スタディサプリ』などの学びを支援するサービスなど、ライフイベント領域に関わるサービスを提供するリクルートグループの中核企業
http://www.recruit-mp.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away